All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-07-06  6:09 ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-06  6:09 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: Marek Vasut, Detlev Zundel, Dong Aisheng, Fabio Estevam,
	Linux ARM kernel, Sascha Hauer, Shawn Guo, Stefano Babic,
	Uwe Kleine-König, Wolfgang Denk, Wolfram Sang

This patch configures the I2C bus timing registers according
to information passed via DT. Currently, 100kHz and 400kHz
modes are supported.

The TIMING2 register value is wrong in the documentation for
i.MX28! This was found and fixed by:
  Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Signed-off-by: Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>
Cc: Detlev Zundel <dzu-ynQEQJNshbs@public.gmane.org>
CC: Dong Aisheng <b29396-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
CC: Fabio Estevam <fabio.estevam-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Cc: Linux ARM kernel <linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
CC: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Stefano Babic <sbabic-ynQEQJNshbs@public.gmane.org>
CC: Uwe Kleine-König <u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Cc: Wolfgang Denk <wd-ynQEQJNshbs@public.gmane.org>
Cc: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    2 +
 arch/arm/boot/dts/imx28.dtsi                      |    2 +
 drivers/i2c/busses/i2c-mxs.c                      |   56 +++++++++++++++++++++
 3 files changed, 60 insertions(+)

V2: (even though technically V<around 4>, I really need to start doing this
     patch management properly, it's quite a mess now)
    Fixed static const struct mxs_i2c_speed_config ... pointed by Dong.

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
index 1bfc02d..2ed5332 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
@@ -4,6 +4,7 @@ Required properties:
 - compatible: Should be "fsl,<chip>-i2c"
 - reg: Should contain registers location and length
 - interrupts: Should contain ERROR and DMA interrupts
+- clock-frequency: desired I2C bus clock frequency in Hz.
 
 Examples:
 
@@ -13,4 +14,5 @@ i2c0: i2c@80058000 {
 	compatible = "fsl,imx28-i2c";
 	reg = <0x80058000 2000>;
 	interrupts = <111 68>;
+	clock-frequency = <400000>;
 };
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index ee3778a..832d30a 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -419,6 +419,7 @@
 				compatible = "fsl,imx28-i2c";
 				reg = <0x80058000 2000>;
 				interrupts = <111 68>;
+				clock-frequency = <400000>;
 				status = "disabled";
 			};
 
@@ -428,6 +429,7 @@
 				compatible = "fsl,imx28-i2c";
 				reg = <0x8005a000 2000>;
 				interrupts = <110 69>;
+				clock-frequency = <400000>;
 				status = "disabled";
 			};
 
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 04eb441..47a7e20 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -46,6 +46,10 @@
 #define MXS_I2C_CTRL0_DIRECTION			0x00010000
 #define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
 
+#define MXS_I2C_TIMING0		(0x10)
+#define MXS_I2C_TIMING1		(0x20)
+#define MXS_I2C_TIMING2		(0x30)
+
 #define MXS_I2C_CTRL1		(0x40)
 #define MXS_I2C_CTRL1_SET	(0x44)
 #define MXS_I2C_CTRL1_CLR	(0x48)
@@ -97,6 +101,25 @@
 #define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
 				 MXS_I2C_CTRL0_MASTER_MODE)
 
+struct mxs_i2c_speed_config {
+	uint32_t	timing0;
+	uint32_t	timing1;
+	uint32_t	timing2;
+};
+
+/* Timing values for the default 24MHz clock supplied into the i2c block. */
+static const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
+	.timing0	= 0x00780030,
+	.timing1	= 0x00800030,
+	.timing2	= 0x00300030,
+};
+
+static const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
+	.timing0	= 0x000f0007,
+	.timing1	= 0x001f000f,
+	.timing2	= 0x00300030,
+};
+
 /**
  * struct mxs_i2c_dev - per device, private MXS-I2C data
  *
@@ -112,11 +135,17 @@ struct mxs_i2c_dev {
 	struct completion cmd_complete;
 	u32 cmd_err;
 	struct i2c_adapter adapter;
+	const struct mxs_i2c_speed_config *speed;
 };
 
 static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
 {
 	stmp_reset_block(i2c->regs);
+
+	writel(i2c->speed->timing0, i2c->regs + MXS_I2C_TIMING0);
+	writel(i2c->speed->timing1, i2c->regs + MXS_I2C_TIMING1);
+	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
+
 	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
 	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
 			i2c->regs + MXS_I2C_QUEUECTRL_SET);
@@ -319,6 +348,28 @@ static const struct i2c_algorithm mxs_i2c_algo = {
 	.functionality = mxs_i2c_func,
 };
 
+static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
+{
+	uint32_t speed;
+	struct device *dev = i2c->dev;
+	struct device_node *node = dev->of_node;
+	int ret;
+
+	if (!node)
+		return -EINVAL;
+
+	i2c->speed = &mxs_i2c_95kHz_config;
+	ret = of_property_read_u32(node, "clock-frequency", &speed);
+	if (ret)
+		dev_warn(dev, "No I2C speed selected, using 100kHz\n");
+	else if (speed == 400000)
+		i2c->speed = &mxs_i2c_400kHz_config;
+	else if (speed != 100000)
+		dev_warn(dev, "Invalid I2C speed selected, using 100kHz\n");
+
+	return 0;
+}
+
 static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -358,6 +409,11 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 		return err;
 
 	i2c->dev = dev;
+
+	err = mxs_i2c_get_ofdata(i2c);
+	if (err)
+		return err;
+
 	platform_set_drvdata(pdev, i2c);
 
 	/* Do reset to enforce correct startup after pinmuxing */
-- 
1.7.10

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-07-06  6:09 ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-06  6:09 UTC (permalink / raw)
  To: linux-arm-kernel

This patch configures the I2C bus timing registers according
to information passed via DT. Currently, 100kHz and 400kHz
modes are supported.

The TIMING2 register value is wrong in the documentation for
i.MX28! This was found and fixed by:
  Shawn Guo <shawn.guo@linaro.org>

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
CC: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: linux-i2c at vger.kernel.org
CC: Sascha Hauer <s.hauer@pengutronix.de>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
CC: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Wolfram Sang <w.sang@pengutronix.de>
---
 Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    2 +
 arch/arm/boot/dts/imx28.dtsi                      |    2 +
 drivers/i2c/busses/i2c-mxs.c                      |   56 +++++++++++++++++++++
 3 files changed, 60 insertions(+)

V2: (even though technically V<around 4>, I really need to start doing this
     patch management properly, it's quite a mess now)
    Fixed static const struct mxs_i2c_speed_config ... pointed by Dong.

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
index 1bfc02d..2ed5332 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
@@ -4,6 +4,7 @@ Required properties:
 - compatible: Should be "fsl,<chip>-i2c"
 - reg: Should contain registers location and length
 - interrupts: Should contain ERROR and DMA interrupts
+- clock-frequency: desired I2C bus clock frequency in Hz.
 
 Examples:
 
@@ -13,4 +14,5 @@ i2c0: i2c at 80058000 {
 	compatible = "fsl,imx28-i2c";
 	reg = <0x80058000 2000>;
 	interrupts = <111 68>;
+	clock-frequency = <400000>;
 };
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index ee3778a..832d30a 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -419,6 +419,7 @@
 				compatible = "fsl,imx28-i2c";
 				reg = <0x80058000 2000>;
 				interrupts = <111 68>;
+				clock-frequency = <400000>;
 				status = "disabled";
 			};
 
@@ -428,6 +429,7 @@
 				compatible = "fsl,imx28-i2c";
 				reg = <0x8005a000 2000>;
 				interrupts = <110 69>;
+				clock-frequency = <400000>;
 				status = "disabled";
 			};
 
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 04eb441..47a7e20 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -46,6 +46,10 @@
 #define MXS_I2C_CTRL0_DIRECTION			0x00010000
 #define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
 
+#define MXS_I2C_TIMING0		(0x10)
+#define MXS_I2C_TIMING1		(0x20)
+#define MXS_I2C_TIMING2		(0x30)
+
 #define MXS_I2C_CTRL1		(0x40)
 #define MXS_I2C_CTRL1_SET	(0x44)
 #define MXS_I2C_CTRL1_CLR	(0x48)
@@ -97,6 +101,25 @@
 #define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
 				 MXS_I2C_CTRL0_MASTER_MODE)
 
+struct mxs_i2c_speed_config {
+	uint32_t	timing0;
+	uint32_t	timing1;
+	uint32_t	timing2;
+};
+
+/* Timing values for the default 24MHz clock supplied into the i2c block. */
+static const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
+	.timing0	= 0x00780030,
+	.timing1	= 0x00800030,
+	.timing2	= 0x00300030,
+};
+
+static const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
+	.timing0	= 0x000f0007,
+	.timing1	= 0x001f000f,
+	.timing2	= 0x00300030,
+};
+
 /**
  * struct mxs_i2c_dev - per device, private MXS-I2C data
  *
@@ -112,11 +135,17 @@ struct mxs_i2c_dev {
 	struct completion cmd_complete;
 	u32 cmd_err;
 	struct i2c_adapter adapter;
+	const struct mxs_i2c_speed_config *speed;
 };
 
 static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
 {
 	stmp_reset_block(i2c->regs);
+
+	writel(i2c->speed->timing0, i2c->regs + MXS_I2C_TIMING0);
+	writel(i2c->speed->timing1, i2c->regs + MXS_I2C_TIMING1);
+	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
+
 	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
 	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
 			i2c->regs + MXS_I2C_QUEUECTRL_SET);
@@ -319,6 +348,28 @@ static const struct i2c_algorithm mxs_i2c_algo = {
 	.functionality = mxs_i2c_func,
 };
 
+static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
+{
+	uint32_t speed;
+	struct device *dev = i2c->dev;
+	struct device_node *node = dev->of_node;
+	int ret;
+
+	if (!node)
+		return -EINVAL;
+
+	i2c->speed = &mxs_i2c_95kHz_config;
+	ret = of_property_read_u32(node, "clock-frequency", &speed);
+	if (ret)
+		dev_warn(dev, "No I2C speed selected, using 100kHz\n");
+	else if (speed == 400000)
+		i2c->speed = &mxs_i2c_400kHz_config;
+	else if (speed != 100000)
+		dev_warn(dev, "Invalid I2C speed selected, using 100kHz\n");
+
+	return 0;
+}
+
 static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -358,6 +409,11 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 		return err;
 
 	i2c->dev = dev;
+
+	err = mxs_i2c_get_ofdata(i2c);
+	if (err)
+		return err;
+
 	platform_set_drvdata(pdev, i2c);
 
 	/* Do reset to enforce correct startup after pinmuxing */
-- 
1.7.10

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

* [PATCH 2/2 V2] MXS: Implement DMA support into mxs-i2c
  2012-07-06  6:09 ` Marek Vasut
@ 2012-07-06  6:09     ` Marek Vasut
  -1 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-06  6:09 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: Marek Vasut, Detlev Zundel, Dong Aisheng, Fabio Estevam,
	Linux ARM kernel, Sascha Hauer, Shawn Guo, Stefano Babic,
	Uwe Kleine-König, Wolfgang Denk, Wolfram Sang

This patch implements DMA support into mxs-i2c. DMA transfers are now enabled
via DT. The DMA operation is enabled by default.

Signed-off-by: Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>
Cc: Detlev Zundel <dzu-ynQEQJNshbs@public.gmane.org>
CC: Dong Aisheng <b29396-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
CC: Fabio Estevam <fabio.estevam-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Cc: Linux ARM kernel <linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
CC: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Stefano Babic <sbabic-ynQEQJNshbs@public.gmane.org>
CC: Uwe Kleine-König <u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Cc: Wolfgang Denk <wd-ynQEQJNshbs@public.gmane.org>
Cc: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    5 +
 arch/arm/boot/dts/imx28.dtsi                      |    2 +
 drivers/i2c/busses/i2c-mxs.c                      |  267 +++++++++++++++++++--
 3 files changed, 252 insertions(+), 22 deletions(-)

V2: (even though technically V<around 4>, ditto here, slaps himself)
    Fixed return value from mxs_i2c_dma_setup_xfer(), pointed by Dong.
    Fixed coding style nitpicks
    Call mxs_i2c_dma_finish() in failpath only if DMA is active

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
index 2ed5332..d337cbc 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
@@ -5,6 +5,10 @@ Required properties:
 - reg: Should contain registers location and length
 - interrupts: Should contain ERROR and DMA interrupts
 - clock-frequency: desired I2C bus clock frequency in Hz.
+- fsl,i2c-dma-channel: APBX DMA channel for the I2C
+
+Optional properties:
+- fsl,use-pio: Use PIO transfers instead of DMA, useful for debug
 
 Examples:
 
@@ -15,4 +19,5 @@ i2c0: i2c@80058000 {
 	reg = <0x80058000 2000>;
 	interrupts = <111 68>;
 	clock-frequency = <400000>;
+	fsl,i2c-dma-channel = <6>;
 };
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 832d30a..e4a4842 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -420,6 +420,7 @@
 				reg = <0x80058000 2000>;
 				interrupts = <111 68>;
 				clock-frequency = <400000>;
+				fsl,i2c-dma-channel = <6>;
 				status = "disabled";
 			};
 
@@ -430,6 +431,7 @@
 				reg = <0x8005a000 2000>;
 				interrupts = <110 69>;
 				clock-frequency = <400000>;
+				fsl,i2c-dma-channel = <7>;
 				status = "disabled";
 			};
 
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 47a7e20..989d4f8 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -7,8 +7,6 @@
  *
  * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
  *
- * TODO: add dma-support if platform-support for it is available
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -31,6 +29,9 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_i2c.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/fsl/mxs-dma.h>
 
 #define DRIVER_NAME "mxs-i2c"
 
@@ -136,6 +137,16 @@ struct mxs_i2c_dev {
 	u32 cmd_err;
 	struct i2c_adapter adapter;
 	const struct mxs_i2c_speed_config *speed;
+
+	/* DMA support components */
+	bool				dma_mode;
+	int				dma_channel;
+	struct dma_chan         	*dmach;
+	struct mxs_dma_data		dma_data;
+	uint32_t			pio_data[2];
+	uint32_t			addr_data;
+	struct scatterlist		sg_io[2];
+	bool				dma_read;
 };
 
 static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
@@ -147,7 +158,11 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
 	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
 
 	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
-	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
+	if (i2c->dma_mode)
+		writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
+			i2c->regs + MXS_I2C_QUEUECTRL_CLR);
+	else
+		writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
 			i2c->regs + MXS_I2C_QUEUECTRL_SET);
 }
 
@@ -238,6 +253,150 @@ static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
 	return 0;
 }
 
+static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
+{
+	if (i2c->dma_read) {
+		dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+		dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+	} else {
+		dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+	}
+}
+
+static void mxs_i2c_dma_irq_callback(void *param)
+{
+	struct mxs_i2c_dev *i2c = param;
+
+	complete(&i2c->cmd_complete);
+	mxs_i2c_dma_finish(i2c);
+}
+
+static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
+			struct i2c_msg *msg, uint32_t flags)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
+
+	if (msg->flags & I2C_M_RD) {
+		i2c->dma_read = 1;
+		i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_READ;
+
+		/*
+		 * SELECT command.
+		 */
+
+		/* Queue the PIO register write transfer. */
+		i2c->pio_data[0] = MXS_CMD_I2C_SELECT;
+		desc = dmaengine_prep_slave_sg(i2c->dmach,
+					(struct scatterlist *)&i2c->pio_data[0],
+					1, DMA_TRANS_NONE, 0);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get PIO reg. write descriptor.\n");
+			goto select_init_pio_fail;
+		}
+
+		/* Queue the DMA data transfer. */
+		sg_init_one(&i2c->sg_io[0], &i2c->addr_data, 1);
+		dma_map_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[0], 1,
+					DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get DMA data write descriptor.\n");
+			goto select_init_dma_fail;
+		}
+
+		/*
+		 * READ command.
+		 */
+
+		/* Queue the PIO register write transfer. */
+		i2c->pio_data[1] = flags | MXS_CMD_I2C_READ |
+				MXS_I2C_CTRL0_XFER_COUNT(msg->len);
+		desc = dmaengine_prep_slave_sg(i2c->dmach,
+					(struct scatterlist *)&i2c->pio_data[1],
+					1, DMA_TRANS_NONE, DMA_PREP_INTERRUPT);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get PIO reg. write descriptor.\n");
+			goto select_init_dma_fail;
+		}
+
+		/* Queue the DMA data transfer. */
+		sg_init_one(&i2c->sg_io[1], msg->buf, msg->len);
+		dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
+					DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get DMA data write descriptor.\n");
+			goto read_init_dma_fail;
+		}
+	} else {
+		i2c->dma_read = 0;
+		i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_WRITE;
+
+		/*
+		 * WRITE command.
+		 */
+
+		/* Queue the PIO register write transfer. */
+		i2c->pio_data[0] = flags | MXS_CMD_I2C_WRITE |
+				MXS_I2C_CTRL0_XFER_COUNT(msg->len + 1);
+		desc = dmaengine_prep_slave_sg(i2c->dmach,
+					(struct scatterlist *)&i2c->pio_data[0],
+					1, DMA_TRANS_NONE, 0);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get PIO reg. write descriptor.\n");
+			goto write_init_pio_fail;
+		}
+
+		/* Queue the DMA data transfer. */
+		sg_init_table(i2c->sg_io, 2);
+		sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1);
+		sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len);
+		dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+		desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
+					DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get DMA data write descriptor.\n");
+			goto write_init_dma_fail;
+		}
+	}
+
+	/*
+	 * The last descriptor must have this callback,
+	 * to finish the DMA transaction.
+	 */
+	desc->callback = mxs_i2c_dma_irq_callback;
+	desc->callback_param = i2c;
+
+	/* Start the transfer. */
+	dmaengine_submit(desc);
+	dma_async_issue_pending(i2c->dmach);
+	return 0;
+
+/* Read failpath. */
+read_init_dma_fail:
+	dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+select_init_dma_fail:
+	dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+select_init_pio_fail:
+	return -EINVAL;
+
+/* Write failpath. */
+write_init_dma_fail:
+	dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+write_init_pio_fail:
+	return -EINVAL;
+}
+
 /*
  * Low level master read/write transaction.
  */
@@ -248,6 +407,8 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 	int ret;
 	int flags;
 
+	flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
+
 	dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
 		msg->addr, msg->len, msg->flags, stop);
 
@@ -257,23 +418,29 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 	init_completion(&i2c->cmd_complete);
 	i2c->cmd_err = 0;
 
-	flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
-
-	if (msg->flags & I2C_M_RD)
-		mxs_i2c_pioq_setup_read(i2c, msg->addr, msg->len, flags);
-	else
-		mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, msg->len,
-					flags);
+	if (i2c->dma_mode) {
+		ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
+		if (ret)
+			return ret;
+	} else {
+		if (msg->flags & I2C_M_RD) {
+			mxs_i2c_pioq_setup_read(i2c, msg->addr,
+						msg->len, flags);
+		} else {
+			mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
+						msg->len, flags);
+		}
 
-	writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+		writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
 			i2c->regs + MXS_I2C_QUEUECTRL_SET);
+	}
 
 	ret = wait_for_completion_timeout(&i2c->cmd_complete,
 						msecs_to_jiffies(1000));
 	if (ret == 0)
 		goto timeout;
 
-	if ((!i2c->cmd_err) && (msg->flags & I2C_M_RD)) {
+	if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
 		ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
 		if (ret)
 			goto timeout;
@@ -291,6 +458,8 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 
 timeout:
 	dev_dbg(i2c->dev, "Timeout!\n");
+	if (i2c->dma_mode)
+		mxs_i2c_dma_finish(i2c);
 	mxs_i2c_reset(i2c);
 	return -ETIMEDOUT;
 }
@@ -332,11 +501,13 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
 		/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
 		i2c->cmd_err = -EIO;
 
-	is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
-		MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
+	if (!i2c->dma_mode) {
+		is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
+			MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
 
-	if (is_last_cmd || i2c->cmd_err)
-		complete(&i2c->cmd_complete);
+		if (is_last_cmd || i2c->cmd_err)
+			complete(&i2c->cmd_complete);
+	}
 
 	writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
 
@@ -348,6 +519,21 @@ static const struct i2c_algorithm mxs_i2c_algo = {
 	.functionality = mxs_i2c_func,
 };
 
+static bool mxs_i2c_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct mxs_i2c_dev *i2c = param;
+
+	if (!mxs_dma_is_apbx(chan))
+		return false;
+
+	if (chan->chan_id != i2c->dma_channel)
+		return false;
+
+	chan->private = &i2c->dma_data;
+
+	return true;
+}
+
 static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
 {
 	uint32_t speed;
@@ -358,6 +544,28 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
 	if (!node)
 		return -EINVAL;
 
+	/*
+	 * The MXS I2C DMA mode is prefered and enabled by default.
+	 * The PIO mode is still supported, but should be used only
+	 * for debuging purposes etc.
+	 */
+	i2c->dma_mode = 1;
+	if (of_find_property(node, "fsl,use-pio", NULL)) {
+		i2c->dma_mode = 0;
+		dev_info(dev, "Using PIO mode for I2C transfers!\n");
+	}
+
+	/*
+	 * TODO: This is a temporary solution and should be changed
+	 * to use generic DMA binding later when the helpers get in.
+	 */
+	ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
+				   &i2c->dma_channel);
+	if (ret) {
+		dev_warn(dev, "Failed to get DMA channel!\n");
+		i2c->dma_mode = 0;
+	}
+
 	i2c->speed = &mxs_i2c_95kHz_config;
 	ret = of_property_read_u32(node, "clock-frequency", &speed);
 	if (ret)
@@ -378,7 +586,8 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 	struct pinctrl *pinctrl;
 	struct resource *res;
 	resource_size_t res_size;
-	int err, irq;
+	int err, irq, dmairq;
+	dma_cap_mask_t mask;
 
 	pinctrl = devm_pinctrl_get_select_default(dev);
 	if (IS_ERR(pinctrl))
@@ -389,7 +598,10 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
+	irq = platform_get_irq(pdev, 0);
+	dmairq = platform_get_irq(pdev, 1);
+
+	if (!res || irq < 0 || dmairq < 0)
 		return -ENOENT;
 
 	res_size = resource_size(res);
@@ -400,10 +612,6 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 	if (!i2c->regs)
 		return -EBUSY;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
 	err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c);
 	if (err)
 		return err;
@@ -414,6 +622,18 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
+	/* Setup the DMA */
+	if (i2c->dma_mode) {
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+		i2c->dma_data.chan_irq = dmairq;
+		i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+		if (!i2c->dmach) {
+			dev_err(dev, "Failed to request dma\n");
+			return -ENODEV;
+		}
+	}
+
 	platform_set_drvdata(pdev, i2c);
 
 	/* Do reset to enforce correct startup after pinmuxing */
@@ -449,6 +669,9 @@ static int __devexit mxs_i2c_remove(struct platform_device *pdev)
 	if (ret)
 		return -EBUSY;
 
+	if (i2c->dmach)
+		dma_release_channel(i2c->dmach);
+
 	writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
 
 	platform_set_drvdata(pdev, NULL);
-- 
1.7.10

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

* [PATCH 2/2 V2] MXS: Implement DMA support into mxs-i2c
@ 2012-07-06  6:09     ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-06  6:09 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements DMA support into mxs-i2c. DMA transfers are now enabled
via DT. The DMA operation is enabled by default.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
CC: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: linux-i2c at vger.kernel.org
CC: Sascha Hauer <s.hauer@pengutronix.de>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
CC: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Wolfram Sang <w.sang@pengutronix.de>
---
 Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    5 +
 arch/arm/boot/dts/imx28.dtsi                      |    2 +
 drivers/i2c/busses/i2c-mxs.c                      |  267 +++++++++++++++++++--
 3 files changed, 252 insertions(+), 22 deletions(-)

V2: (even though technically V<around 4>, ditto here, slaps himself)
    Fixed return value from mxs_i2c_dma_setup_xfer(), pointed by Dong.
    Fixed coding style nitpicks
    Call mxs_i2c_dma_finish() in failpath only if DMA is active

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
index 2ed5332..d337cbc 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
@@ -5,6 +5,10 @@ Required properties:
 - reg: Should contain registers location and length
 - interrupts: Should contain ERROR and DMA interrupts
 - clock-frequency: desired I2C bus clock frequency in Hz.
+- fsl,i2c-dma-channel: APBX DMA channel for the I2C
+
+Optional properties:
+- fsl,use-pio: Use PIO transfers instead of DMA, useful for debug
 
 Examples:
 
@@ -15,4 +19,5 @@ i2c0: i2c at 80058000 {
 	reg = <0x80058000 2000>;
 	interrupts = <111 68>;
 	clock-frequency = <400000>;
+	fsl,i2c-dma-channel = <6>;
 };
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 832d30a..e4a4842 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -420,6 +420,7 @@
 				reg = <0x80058000 2000>;
 				interrupts = <111 68>;
 				clock-frequency = <400000>;
+				fsl,i2c-dma-channel = <6>;
 				status = "disabled";
 			};
 
@@ -430,6 +431,7 @@
 				reg = <0x8005a000 2000>;
 				interrupts = <110 69>;
 				clock-frequency = <400000>;
+				fsl,i2c-dma-channel = <7>;
 				status = "disabled";
 			};
 
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 47a7e20..989d4f8 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -7,8 +7,6 @@
  *
  * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
  *
- * TODO: add dma-support if platform-support for it is available
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -31,6 +29,9 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_i2c.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/fsl/mxs-dma.h>
 
 #define DRIVER_NAME "mxs-i2c"
 
@@ -136,6 +137,16 @@ struct mxs_i2c_dev {
 	u32 cmd_err;
 	struct i2c_adapter adapter;
 	const struct mxs_i2c_speed_config *speed;
+
+	/* DMA support components */
+	bool				dma_mode;
+	int				dma_channel;
+	struct dma_chan         	*dmach;
+	struct mxs_dma_data		dma_data;
+	uint32_t			pio_data[2];
+	uint32_t			addr_data;
+	struct scatterlist		sg_io[2];
+	bool				dma_read;
 };
 
 static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
@@ -147,7 +158,11 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
 	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
 
 	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
-	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
+	if (i2c->dma_mode)
+		writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
+			i2c->regs + MXS_I2C_QUEUECTRL_CLR);
+	else
+		writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
 			i2c->regs + MXS_I2C_QUEUECTRL_SET);
 }
 
@@ -238,6 +253,150 @@ static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
 	return 0;
 }
 
+static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
+{
+	if (i2c->dma_read) {
+		dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+		dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+	} else {
+		dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+	}
+}
+
+static void mxs_i2c_dma_irq_callback(void *param)
+{
+	struct mxs_i2c_dev *i2c = param;
+
+	complete(&i2c->cmd_complete);
+	mxs_i2c_dma_finish(i2c);
+}
+
+static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
+			struct i2c_msg *msg, uint32_t flags)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
+
+	if (msg->flags & I2C_M_RD) {
+		i2c->dma_read = 1;
+		i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_READ;
+
+		/*
+		 * SELECT command.
+		 */
+
+		/* Queue the PIO register write transfer. */
+		i2c->pio_data[0] = MXS_CMD_I2C_SELECT;
+		desc = dmaengine_prep_slave_sg(i2c->dmach,
+					(struct scatterlist *)&i2c->pio_data[0],
+					1, DMA_TRANS_NONE, 0);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get PIO reg. write descriptor.\n");
+			goto select_init_pio_fail;
+		}
+
+		/* Queue the DMA data transfer. */
+		sg_init_one(&i2c->sg_io[0], &i2c->addr_data, 1);
+		dma_map_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[0], 1,
+					DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get DMA data write descriptor.\n");
+			goto select_init_dma_fail;
+		}
+
+		/*
+		 * READ command.
+		 */
+
+		/* Queue the PIO register write transfer. */
+		i2c->pio_data[1] = flags | MXS_CMD_I2C_READ |
+				MXS_I2C_CTRL0_XFER_COUNT(msg->len);
+		desc = dmaengine_prep_slave_sg(i2c->dmach,
+					(struct scatterlist *)&i2c->pio_data[1],
+					1, DMA_TRANS_NONE, DMA_PREP_INTERRUPT);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get PIO reg. write descriptor.\n");
+			goto select_init_dma_fail;
+		}
+
+		/* Queue the DMA data transfer. */
+		sg_init_one(&i2c->sg_io[1], msg->buf, msg->len);
+		dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
+					DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get DMA data write descriptor.\n");
+			goto read_init_dma_fail;
+		}
+	} else {
+		i2c->dma_read = 0;
+		i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_WRITE;
+
+		/*
+		 * WRITE command.
+		 */
+
+		/* Queue the PIO register write transfer. */
+		i2c->pio_data[0] = flags | MXS_CMD_I2C_WRITE |
+				MXS_I2C_CTRL0_XFER_COUNT(msg->len + 1);
+		desc = dmaengine_prep_slave_sg(i2c->dmach,
+					(struct scatterlist *)&i2c->pio_data[0],
+					1, DMA_TRANS_NONE, 0);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get PIO reg. write descriptor.\n");
+			goto write_init_pio_fail;
+		}
+
+		/* Queue the DMA data transfer. */
+		sg_init_table(i2c->sg_io, 2);
+		sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1);
+		sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len);
+		dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+		desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
+					DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+		if (!desc) {
+			dev_err(i2c->dev,
+				"Failed to get DMA data write descriptor.\n");
+			goto write_init_dma_fail;
+		}
+	}
+
+	/*
+	 * The last descriptor must have this callback,
+	 * to finish the DMA transaction.
+	 */
+	desc->callback = mxs_i2c_dma_irq_callback;
+	desc->callback_param = i2c;
+
+	/* Start the transfer. */
+	dmaengine_submit(desc);
+	dma_async_issue_pending(i2c->dmach);
+	return 0;
+
+/* Read failpath. */
+read_init_dma_fail:
+	dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
+select_init_dma_fail:
+	dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
+select_init_pio_fail:
+	return -EINVAL;
+
+/* Write failpath. */
+write_init_dma_fail:
+	dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
+write_init_pio_fail:
+	return -EINVAL;
+}
+
 /*
  * Low level master read/write transaction.
  */
@@ -248,6 +407,8 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 	int ret;
 	int flags;
 
+	flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
+
 	dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
 		msg->addr, msg->len, msg->flags, stop);
 
@@ -257,23 +418,29 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 	init_completion(&i2c->cmd_complete);
 	i2c->cmd_err = 0;
 
-	flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
-
-	if (msg->flags & I2C_M_RD)
-		mxs_i2c_pioq_setup_read(i2c, msg->addr, msg->len, flags);
-	else
-		mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, msg->len,
-					flags);
+	if (i2c->dma_mode) {
+		ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
+		if (ret)
+			return ret;
+	} else {
+		if (msg->flags & I2C_M_RD) {
+			mxs_i2c_pioq_setup_read(i2c, msg->addr,
+						msg->len, flags);
+		} else {
+			mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
+						msg->len, flags);
+		}
 
-	writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+		writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
 			i2c->regs + MXS_I2C_QUEUECTRL_SET);
+	}
 
 	ret = wait_for_completion_timeout(&i2c->cmd_complete,
 						msecs_to_jiffies(1000));
 	if (ret == 0)
 		goto timeout;
 
-	if ((!i2c->cmd_err) && (msg->flags & I2C_M_RD)) {
+	if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
 		ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
 		if (ret)
 			goto timeout;
@@ -291,6 +458,8 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 
 timeout:
 	dev_dbg(i2c->dev, "Timeout!\n");
+	if (i2c->dma_mode)
+		mxs_i2c_dma_finish(i2c);
 	mxs_i2c_reset(i2c);
 	return -ETIMEDOUT;
 }
@@ -332,11 +501,13 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
 		/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
 		i2c->cmd_err = -EIO;
 
-	is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
-		MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
+	if (!i2c->dma_mode) {
+		is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
+			MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
 
-	if (is_last_cmd || i2c->cmd_err)
-		complete(&i2c->cmd_complete);
+		if (is_last_cmd || i2c->cmd_err)
+			complete(&i2c->cmd_complete);
+	}
 
 	writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
 
@@ -348,6 +519,21 @@ static const struct i2c_algorithm mxs_i2c_algo = {
 	.functionality = mxs_i2c_func,
 };
 
+static bool mxs_i2c_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct mxs_i2c_dev *i2c = param;
+
+	if (!mxs_dma_is_apbx(chan))
+		return false;
+
+	if (chan->chan_id != i2c->dma_channel)
+		return false;
+
+	chan->private = &i2c->dma_data;
+
+	return true;
+}
+
 static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
 {
 	uint32_t speed;
@@ -358,6 +544,28 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
 	if (!node)
 		return -EINVAL;
 
+	/*
+	 * The MXS I2C DMA mode is prefered and enabled by default.
+	 * The PIO mode is still supported, but should be used only
+	 * for debuging purposes etc.
+	 */
+	i2c->dma_mode = 1;
+	if (of_find_property(node, "fsl,use-pio", NULL)) {
+		i2c->dma_mode = 0;
+		dev_info(dev, "Using PIO mode for I2C transfers!\n");
+	}
+
+	/*
+	 * TODO: This is a temporary solution and should be changed
+	 * to use generic DMA binding later when the helpers get in.
+	 */
+	ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
+				   &i2c->dma_channel);
+	if (ret) {
+		dev_warn(dev, "Failed to get DMA channel!\n");
+		i2c->dma_mode = 0;
+	}
+
 	i2c->speed = &mxs_i2c_95kHz_config;
 	ret = of_property_read_u32(node, "clock-frequency", &speed);
 	if (ret)
@@ -378,7 +586,8 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 	struct pinctrl *pinctrl;
 	struct resource *res;
 	resource_size_t res_size;
-	int err, irq;
+	int err, irq, dmairq;
+	dma_cap_mask_t mask;
 
 	pinctrl = devm_pinctrl_get_select_default(dev);
 	if (IS_ERR(pinctrl))
@@ -389,7 +598,10 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
+	irq = platform_get_irq(pdev, 0);
+	dmairq = platform_get_irq(pdev, 1);
+
+	if (!res || irq < 0 || dmairq < 0)
 		return -ENOENT;
 
 	res_size = resource_size(res);
@@ -400,10 +612,6 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 	if (!i2c->regs)
 		return -EBUSY;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
 	err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c);
 	if (err)
 		return err;
@@ -414,6 +622,18 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
+	/* Setup the DMA */
+	if (i2c->dma_mode) {
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+		i2c->dma_data.chan_irq = dmairq;
+		i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+		if (!i2c->dmach) {
+			dev_err(dev, "Failed to request dma\n");
+			return -ENODEV;
+		}
+	}
+
 	platform_set_drvdata(pdev, i2c);
 
 	/* Do reset to enforce correct startup after pinmuxing */
@@ -449,6 +669,9 @@ static int __devexit mxs_i2c_remove(struct platform_device *pdev)
 	if (ret)
 		return -EBUSY;
 
+	if (i2c->dmach)
+		dma_release_channel(i2c->dmach);
+
 	writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
 
 	platform_set_drvdata(pdev, NULL);
-- 
1.7.10

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-07-06  6:09 ` Marek Vasut
@ 2012-07-09 10:53     ` Wolfram Sang
  -1 siblings, 0 replies; 34+ messages in thread
From: Wolfram Sang @ 2012-07-09 10:53 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Detlev Zundel, Dong Aisheng,
	Fabio Estevam, Linux ARM kernel, Sascha Hauer, Shawn Guo,
	Stefano Babic, Uwe Kleine-König, Wolfgang Denk

[-- Attachment #1: Type: text/plain, Size: 6871 bytes --]

Hi Marek,

thanks for the submission.

On Fri, Jul 06, 2012 at 08:09:15AM +0200, Marek Vasut wrote:
> This patch configures the I2C bus timing registers according
> to information passed via DT. Currently, 100kHz and 400kHz
> modes are supported.

That limitation should be mentioned in the documentation.

> 
> The TIMING2 register value is wrong in the documentation for
> i.MX28! This was found and fixed by:
>   Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> 
> Signed-off-by: Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>
> Cc: Detlev Zundel <dzu-ynQEQJNshbs@public.gmane.org>
> CC: Dong Aisheng <b29396-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> CC: Fabio Estevam <fabio.estevam-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> Cc: Linux ARM kernel <linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
> Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> CC: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> CC: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Stefano Babic <sbabic-ynQEQJNshbs@public.gmane.org>
> CC: Uwe Kleine-König <u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Cc: Wolfgang Denk <wd-ynQEQJNshbs@public.gmane.org>
> Cc: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    2 +
>  arch/arm/boot/dts/imx28.dtsi                      |    2 +
>  drivers/i2c/busses/i2c-mxs.c                      |   56 +++++++++++++++++++++
>  3 files changed, 60 insertions(+)
> 
> V2: (even though technically V<around 4>, I really need to start doing this
>      patch management properly, it's quite a mess now)

Yup, it was :) Thanks for resending.

>     Fixed static const struct mxs_i2c_speed_config ... pointed by Dong.
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> index 1bfc02d..2ed5332 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> @@ -4,6 +4,7 @@ Required properties:
>  - compatible: Should be "fsl,<chip>-i2c"
>  - reg: Should contain registers location and length
>  - interrupts: Should contain ERROR and DMA interrupts
> +- clock-frequency: desired I2C bus clock frequency in Hz.
>  
>  Examples:
>  
> @@ -13,4 +14,5 @@ i2c0: i2c@80058000 {
>  	compatible = "fsl,imx28-i2c";
>  	reg = <0x80058000 2000>;
>  	interrupts = <111 68>;
> +	clock-frequency = <400000>;
>  };
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index ee3778a..832d30a 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -419,6 +419,7 @@
>  				compatible = "fsl,imx28-i2c";
>  				reg = <0x80058000 2000>;
>  				interrupts = <111 68>;
> +				clock-frequency = <400000>;
>  				status = "disabled";
>  			};
>  
> @@ -428,6 +429,7 @@
>  				compatible = "fsl,imx28-i2c";
>  				reg = <0x8005a000 2000>;
>  				interrupts = <110 69>;
> +				clock-frequency = <400000>;

NACK on that. Not all slaves can do 400KHz, so this is not a sensible
default.

>  				status = "disabled";
>  			};
>  
> diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
> index 04eb441..47a7e20 100644
> --- a/drivers/i2c/busses/i2c-mxs.c
> +++ b/drivers/i2c/busses/i2c-mxs.c
> @@ -46,6 +46,10 @@
>  #define MXS_I2C_CTRL0_DIRECTION			0x00010000
>  #define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
>  
> +#define MXS_I2C_TIMING0		(0x10)
> +#define MXS_I2C_TIMING1		(0x20)
> +#define MXS_I2C_TIMING2		(0x30)
> +
>  #define MXS_I2C_CTRL1		(0x40)
>  #define MXS_I2C_CTRL1_SET	(0x44)
>  #define MXS_I2C_CTRL1_CLR	(0x48)
> @@ -97,6 +101,25 @@
>  #define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
>  				 MXS_I2C_CTRL0_MASTER_MODE)
>  
> +struct mxs_i2c_speed_config {
> +	uint32_t	timing0;
> +	uint32_t	timing1;
> +	uint32_t	timing2;
> +};
> +
> +/* Timing values for the default 24MHz clock supplied into the i2c block. */
> +static const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {

Hmm, the 100KHz vs 95KHz issue is confusing. My suggestion would be to
name this mxs_i2c_100kHz_config and write a comment that this is
technically 95Khz due to limitation of the docs (or whatever). If you
want to keep the name, then a similar comment should be placed...


> +	.timing0	= 0x00780030,
> +	.timing1	= 0x00800030,
> +	.timing2	= 0x00300030,
> +};
> +
> +static const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> +	.timing0	= 0x000f0007,
> +	.timing1	= 0x001f000f,
> +	.timing2	= 0x00300030,
> +};
> +
>  /**
>   * struct mxs_i2c_dev - per device, private MXS-I2C data
>   *
> @@ -112,11 +135,17 @@ struct mxs_i2c_dev {
>  	struct completion cmd_complete;
>  	u32 cmd_err;
>  	struct i2c_adapter adapter;
> +	const struct mxs_i2c_speed_config *speed;
>  };
>  
>  static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
>  {
>  	stmp_reset_block(i2c->regs);
> +
> +	writel(i2c->speed->timing0, i2c->regs + MXS_I2C_TIMING0);
> +	writel(i2c->speed->timing1, i2c->regs + MXS_I2C_TIMING1);
> +	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
> +
>  	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
>  	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
>  			i2c->regs + MXS_I2C_QUEUECTRL_SET);
> @@ -319,6 +348,28 @@ static const struct i2c_algorithm mxs_i2c_algo = {
>  	.functionality = mxs_i2c_func,
>  };
>  
> +static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
> +{
> +	uint32_t speed;
> +	struct device *dev = i2c->dev;
> +	struct device_node *node = dev->of_node;
> +	int ret;
> +
> +	if (!node)
> +		return -EINVAL;
> +
> +	i2c->speed = &mxs_i2c_95kHz_config;

...here

> +	ret = of_property_read_u32(node, "clock-frequency", &speed);
> +	if (ret)
> +		dev_warn(dev, "No I2C speed selected, using 100kHz\n");
> +	else if (speed == 400000)
> +		i2c->speed = &mxs_i2c_400kHz_config;
> +	else if (speed != 100000)
> +		dev_warn(dev, "Invalid I2C speed selected, using 100kHz\n");

Minor: s/Invalid/Unsupported/ ?

> +
> +	return 0;
> +}
> +
>  static int __devinit mxs_i2c_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -358,6 +409,11 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
>  		return err;
>  
>  	i2c->dev = dev;
> +
> +	err = mxs_i2c_get_ofdata(i2c);
> +	if (err)
> +		return err;
> +
>  	platform_set_drvdata(pdev, i2c);
>  
>  	/* Do reset to enforce correct startup after pinmuxing */
> -- 
> 1.7.10
> 

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-07-09 10:53     ` Wolfram Sang
  0 siblings, 0 replies; 34+ messages in thread
From: Wolfram Sang @ 2012-07-09 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marek,

thanks for the submission.

On Fri, Jul 06, 2012 at 08:09:15AM +0200, Marek Vasut wrote:
> This patch configures the I2C bus timing registers according
> to information passed via DT. Currently, 100kHz and 400kHz
> modes are supported.

That limitation should be mentioned in the documentation.

> 
> The TIMING2 register value is wrong in the documentation for
> i.MX28! This was found and fixed by:
>   Shawn Guo <shawn.guo@linaro.org>
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> CC: Dong Aisheng <b29396@freescale.com>
> CC: Fabio Estevam <fabio.estevam@freescale.com>
> Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
> Cc: linux-i2c at vger.kernel.org
> CC: Sascha Hauer <s.hauer@pengutronix.de>
> CC: Shawn Guo <shawn.guo@linaro.org>
> Cc: Stefano Babic <sbabic@denx.de>
> CC: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Wolfram Sang <w.sang@pengutronix.de>
> ---
>  Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    2 +
>  arch/arm/boot/dts/imx28.dtsi                      |    2 +
>  drivers/i2c/busses/i2c-mxs.c                      |   56 +++++++++++++++++++++
>  3 files changed, 60 insertions(+)
> 
> V2: (even though technically V<around 4>, I really need to start doing this
>      patch management properly, it's quite a mess now)

Yup, it was :) Thanks for resending.

>     Fixed static const struct mxs_i2c_speed_config ... pointed by Dong.
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> index 1bfc02d..2ed5332 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> @@ -4,6 +4,7 @@ Required properties:
>  - compatible: Should be "fsl,<chip>-i2c"
>  - reg: Should contain registers location and length
>  - interrupts: Should contain ERROR and DMA interrupts
> +- clock-frequency: desired I2C bus clock frequency in Hz.
>  
>  Examples:
>  
> @@ -13,4 +14,5 @@ i2c0: i2c at 80058000 {
>  	compatible = "fsl,imx28-i2c";
>  	reg = <0x80058000 2000>;
>  	interrupts = <111 68>;
> +	clock-frequency = <400000>;
>  };
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index ee3778a..832d30a 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -419,6 +419,7 @@
>  				compatible = "fsl,imx28-i2c";
>  				reg = <0x80058000 2000>;
>  				interrupts = <111 68>;
> +				clock-frequency = <400000>;
>  				status = "disabled";
>  			};
>  
> @@ -428,6 +429,7 @@
>  				compatible = "fsl,imx28-i2c";
>  				reg = <0x8005a000 2000>;
>  				interrupts = <110 69>;
> +				clock-frequency = <400000>;

NACK on that. Not all slaves can do 400KHz, so this is not a sensible
default.

>  				status = "disabled";
>  			};
>  
> diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
> index 04eb441..47a7e20 100644
> --- a/drivers/i2c/busses/i2c-mxs.c
> +++ b/drivers/i2c/busses/i2c-mxs.c
> @@ -46,6 +46,10 @@
>  #define MXS_I2C_CTRL0_DIRECTION			0x00010000
>  #define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
>  
> +#define MXS_I2C_TIMING0		(0x10)
> +#define MXS_I2C_TIMING1		(0x20)
> +#define MXS_I2C_TIMING2		(0x30)
> +
>  #define MXS_I2C_CTRL1		(0x40)
>  #define MXS_I2C_CTRL1_SET	(0x44)
>  #define MXS_I2C_CTRL1_CLR	(0x48)
> @@ -97,6 +101,25 @@
>  #define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
>  				 MXS_I2C_CTRL0_MASTER_MODE)
>  
> +struct mxs_i2c_speed_config {
> +	uint32_t	timing0;
> +	uint32_t	timing1;
> +	uint32_t	timing2;
> +};
> +
> +/* Timing values for the default 24MHz clock supplied into the i2c block. */
> +static const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {

Hmm, the 100KHz vs 95KHz issue is confusing. My suggestion would be to
name this mxs_i2c_100kHz_config and write a comment that this is
technically 95Khz due to limitation of the docs (or whatever). If you
want to keep the name, then a similar comment should be placed...


> +	.timing0	= 0x00780030,
> +	.timing1	= 0x00800030,
> +	.timing2	= 0x00300030,
> +};
> +
> +static const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> +	.timing0	= 0x000f0007,
> +	.timing1	= 0x001f000f,
> +	.timing2	= 0x00300030,
> +};
> +
>  /**
>   * struct mxs_i2c_dev - per device, private MXS-I2C data
>   *
> @@ -112,11 +135,17 @@ struct mxs_i2c_dev {
>  	struct completion cmd_complete;
>  	u32 cmd_err;
>  	struct i2c_adapter adapter;
> +	const struct mxs_i2c_speed_config *speed;
>  };
>  
>  static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
>  {
>  	stmp_reset_block(i2c->regs);
> +
> +	writel(i2c->speed->timing0, i2c->regs + MXS_I2C_TIMING0);
> +	writel(i2c->speed->timing1, i2c->regs + MXS_I2C_TIMING1);
> +	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
> +
>  	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
>  	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
>  			i2c->regs + MXS_I2C_QUEUECTRL_SET);
> @@ -319,6 +348,28 @@ static const struct i2c_algorithm mxs_i2c_algo = {
>  	.functionality = mxs_i2c_func,
>  };
>  
> +static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
> +{
> +	uint32_t speed;
> +	struct device *dev = i2c->dev;
> +	struct device_node *node = dev->of_node;
> +	int ret;
> +
> +	if (!node)
> +		return -EINVAL;
> +
> +	i2c->speed = &mxs_i2c_95kHz_config;

...here

> +	ret = of_property_read_u32(node, "clock-frequency", &speed);
> +	if (ret)
> +		dev_warn(dev, "No I2C speed selected, using 100kHz\n");
> +	else if (speed == 400000)
> +		i2c->speed = &mxs_i2c_400kHz_config;
> +	else if (speed != 100000)
> +		dev_warn(dev, "Invalid I2C speed selected, using 100kHz\n");

Minor: s/Invalid/Unsupported/ ?

> +
> +	return 0;
> +}
> +
>  static int __devinit mxs_i2c_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -358,6 +409,11 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
>  		return err;
>  
>  	i2c->dev = dev;
> +
> +	err = mxs_i2c_get_ofdata(i2c);
> +	if (err)
> +		return err;
> +
>  	platform_set_drvdata(pdev, i2c);
>  
>  	/* Do reset to enforce correct startup after pinmuxing */
> -- 
> 1.7.10
> 

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120709/a1602a2d/attachment.sig>

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-07-09 10:53     ` Wolfram Sang
@ 2012-07-09 11:07         ` Marek Vasut
  -1 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-09 11:07 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Detlev Zundel, Dong Aisheng,
	Fabio Estevam, Linux ARM kernel, Sascha Hauer, Shawn Guo,
	Stefano Babic, Uwe Kleine-König, Wolfgang Denk

Dear Wolfram Sang,

[...]

> > diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> > index ee3778a..832d30a 100644
> > --- a/arch/arm/boot/dts/imx28.dtsi
> > +++ b/arch/arm/boot/dts/imx28.dtsi
[...]
> > @@ -428,6 +429,7 @@
> > 
> >  				compatible = "fsl,imx28-i2c";
> >  				reg = <0x8005a000 2000>;
> >  				interrupts = <110 69>;
> > 
> > +				clock-frequency = <400000>;
> 
> NACK on that. Not all slaves can do 400KHz, so this is not a sensible
> default.

How many of such chips are there and how many of the chips can do 400kHz ? I 
believe the majority shouldn't suffer because of minority.

[...]

Best regards,
Marek Vasut

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-07-09 11:07         ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-09 11:07 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Wolfram Sang,

[...]

> > diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> > index ee3778a..832d30a 100644
> > --- a/arch/arm/boot/dts/imx28.dtsi
> > +++ b/arch/arm/boot/dts/imx28.dtsi
[...]
> > @@ -428,6 +429,7 @@
> > 
> >  				compatible = "fsl,imx28-i2c";
> >  				reg = <0x8005a000 2000>;
> >  				interrupts = <110 69>;
> > 
> > +				clock-frequency = <400000>;
> 
> NACK on that. Not all slaves can do 400KHz, so this is not a sensible
> default.

How many of such chips are there and how many of the chips can do 400kHz ? I 
believe the majority shouldn't suffer because of minority.

[...]

Best regards,
Marek Vasut

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-07-09 11:07         ` Marek Vasut
@ 2012-07-09 12:05             ` Wolfram Sang
  -1 siblings, 0 replies; 34+ messages in thread
From: Wolfram Sang @ 2012-07-09 12:05 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Detlev Zundel, Dong Aisheng,
	Fabio Estevam, Linux ARM kernel, Sascha Hauer, Shawn Guo,
	Stefano Babic, Uwe Kleine-König, Wolfgang Denk

[-- Attachment #1: Type: text/plain, Size: 1186 bytes --]


> > > diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> > > index ee3778a..832d30a 100644
> > > --- a/arch/arm/boot/dts/imx28.dtsi
> > > +++ b/arch/arm/boot/dts/imx28.dtsi
> [...]
> > > @@ -428,6 +429,7 @@
> > > 
> > >  				compatible = "fsl,imx28-i2c";
> > >  				reg = <0x8005a000 2000>;
> > >  				interrupts = <110 69>;
> > > 
> > > +				clock-frequency = <400000>;
> > 
> > NACK on that. Not all slaves can do 400KHz, so this is not a sensible
> > default.
> 
> How many of such chips are there and how many of the chips can do 400kHz ? I 
> believe the majority shouldn't suffer because of minority.

The kernel should work for all users, not only for the majority, so:
Better safe than sorry.

Also, defaults should make the system work. Tuning can be done later by
somebody who understands what is needed.

And frankly, this attitude which made you add a potential regression is
worrisome. I'd suggest to give stability a higher priority.

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-07-09 12:05             ` Wolfram Sang
  0 siblings, 0 replies; 34+ messages in thread
From: Wolfram Sang @ 2012-07-09 12:05 UTC (permalink / raw)
  To: linux-arm-kernel


> > > diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> > > index ee3778a..832d30a 100644
> > > --- a/arch/arm/boot/dts/imx28.dtsi
> > > +++ b/arch/arm/boot/dts/imx28.dtsi
> [...]
> > > @@ -428,6 +429,7 @@
> > > 
> > >  				compatible = "fsl,imx28-i2c";
> > >  				reg = <0x8005a000 2000>;
> > >  				interrupts = <110 69>;
> > > 
> > > +				clock-frequency = <400000>;
> > 
> > NACK on that. Not all slaves can do 400KHz, so this is not a sensible
> > default.
> 
> How many of such chips are there and how many of the chips can do 400kHz ? I 
> believe the majority shouldn't suffer because of minority.

The kernel should work for all users, not only for the majority, so:
Better safe than sorry.

Also, defaults should make the system work. Tuning can be done later by
somebody who understands what is needed.

And frankly, this attitude which made you add a potential regression is
worrisome. I'd suggest to give stability a higher priority.

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120709/e81f2bc3/attachment.sig>

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-07-09 12:05             ` Wolfram Sang
@ 2012-07-09 15:58                 ` Marek Vasut
  -1 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-09 15:58 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Detlev Zundel, Dong Aisheng,
	Fabio Estevam, Linux ARM kernel, Sascha Hauer, Shawn Guo,
	Stefano Babic, Uwe Kleine-König, Wolfgang Denk

Dear Wolfram Sang,

> > > > diff --git a/arch/arm/boot/dts/imx28.dtsi
> > > > b/arch/arm/boot/dts/imx28.dtsi index ee3778a..832d30a 100644
> > > > --- a/arch/arm/boot/dts/imx28.dtsi
> > > > +++ b/arch/arm/boot/dts/imx28.dtsi
> > 
> > [...]
> > 
> > > > @@ -428,6 +429,7 @@
> > > > 
> > > >  				compatible = "fsl,imx28-i2c";
> > > >  				reg = <0x8005a000 2000>;
> > > >  				interrupts = <110 69>;
> > > > 
> > > > +				clock-frequency = <400000>;
> > > 
> > > NACK on that. Not all slaves can do 400KHz, so this is not a sensible
> > > default.
> > 
> > How many of such chips are there and how many of the chips can do 400kHz
> > ? I believe the majority shouldn't suffer because of minority.
> 
> The kernel should work for all users, not only for the majority, so:
> Better safe than sorry.
> 
> Also, defaults should make the system work. Tuning can be done later by
> somebody who understands what is needed.
> 
> And frankly, this attitude which made you add a potential regression is
> worrisome. I'd suggest to give stability a higher priority.

I believe you misunderstood my intention. Setting it to 400kHz was done because 
it's what most people will use, therefore avoiding duplication (most of the 
board files will override this setting now). All right, your sane defaults here 
can be applied, I won't argue.

And frankly, you could have left the last jab out. Let's avoid attacking each 
other, I'm not in the mood for it today.

> Regards,
> 
>    Wolfram

Best regards,
Marek Vasut

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-07-09 15:58                 ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-09 15:58 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Wolfram Sang,

> > > > diff --git a/arch/arm/boot/dts/imx28.dtsi
> > > > b/arch/arm/boot/dts/imx28.dtsi index ee3778a..832d30a 100644
> > > > --- a/arch/arm/boot/dts/imx28.dtsi
> > > > +++ b/arch/arm/boot/dts/imx28.dtsi
> > 
> > [...]
> > 
> > > > @@ -428,6 +429,7 @@
> > > > 
> > > >  				compatible = "fsl,imx28-i2c";
> > > >  				reg = <0x8005a000 2000>;
> > > >  				interrupts = <110 69>;
> > > > 
> > > > +				clock-frequency = <400000>;
> > > 
> > > NACK on that. Not all slaves can do 400KHz, so this is not a sensible
> > > default.
> > 
> > How many of such chips are there and how many of the chips can do 400kHz
> > ? I believe the majority shouldn't suffer because of minority.
> 
> The kernel should work for all users, not only for the majority, so:
> Better safe than sorry.
> 
> Also, defaults should make the system work. Tuning can be done later by
> somebody who understands what is needed.
> 
> And frankly, this attitude which made you add a potential regression is
> worrisome. I'd suggest to give stability a higher priority.

I believe you misunderstood my intention. Setting it to 400kHz was done because 
it's what most people will use, therefore avoiding duplication (most of the 
board files will override this setting now). All right, your sane defaults here 
can be applied, I won't argue.

And frankly, you could have left the last jab out. Let's avoid attacking each 
other, I'm not in the mood for it today.

> Regards,
> 
>    Wolfram

Best regards,
Marek Vasut

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-07-09 15:58                 ` Marek Vasut
@ 2012-07-10 14:09                     ` Robert Schwebel
  -1 siblings, 0 replies; 34+ messages in thread
From: Robert Schwebel @ 2012-07-10 14:09 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Wolfram Sang, Fabio Estevam, Wolfgang Denk, Detlev Zundel,
	Stefano Babic, Sascha Hauer, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	Uwe Kleine-König, Shawn Guo, Dong Aisheng, Linux ARM kernel

On Mon, Jul 09, 2012 at 05:58:22PM +0200, Marek Vasut wrote:
> > The kernel should work for all users, not only for the majority, so:
> > Better safe than sorry.
> >
> > Also, defaults should make the system work. Tuning can be done later by
> > somebody who understands what is needed.
> >
> > And frankly, this attitude which made you add a potential regression is
> > worrisome. I'd suggest to give stability a higher priority.
>
> I believe you misunderstood my intention. Setting it to 400kHz was done because
> it's what most people will use, therefore avoiding duplication (most of the
> board files will override this setting now). All right, your sane defaults here
> can be applied, I won't argue.

I think all I2C chips support 100 kHz, but only selected ones support
400 kHz.

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-07-10 14:09                     ` Robert Schwebel
  0 siblings, 0 replies; 34+ messages in thread
From: Robert Schwebel @ 2012-07-10 14:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 09, 2012 at 05:58:22PM +0200, Marek Vasut wrote:
> > The kernel should work for all users, not only for the majority, so:
> > Better safe than sorry.
> >
> > Also, defaults should make the system work. Tuning can be done later by
> > somebody who understands what is needed.
> >
> > And frankly, this attitude which made you add a potential regression is
> > worrisome. I'd suggest to give stability a higher priority.
>
> I believe you misunderstood my intention. Setting it to 400kHz was done because
> it's what most people will use, therefore avoiding duplication (most of the
> board files will override this setting now). All right, your sane defaults here
> can be applied, I won't argue.

I think all I2C chips support 100 kHz, but only selected ones support
400 kHz.

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-07-10 14:09                     ` Robert Schwebel
@ 2012-07-10 15:13                         ` Marek Vasut
  -1 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-10 15:13 UTC (permalink / raw)
  To: Robert Schwebel
  Cc: Wolfram Sang, Fabio Estevam, Wolfgang Denk, Detlev Zundel,
	Stefano Babic, Sascha Hauer, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	Uwe Kleine-König, Shawn Guo, Dong Aisheng, Linux ARM kernel

Dear Robert Schwebel,

> On Mon, Jul 09, 2012 at 05:58:22PM +0200, Marek Vasut wrote:
> > > The kernel should work for all users, not only for the majority, so:
> > > Better safe than sorry.
> > > 
> > > Also, defaults should make the system work. Tuning can be done later by
> > > somebody who understands what is needed.
> > > 
> > > And frankly, this attitude which made you add a potential regression is
> > > worrisome. I'd suggest to give stability a higher priority.
> > 
> > I believe you misunderstood my intention. Setting it to 400kHz was done
> > because it's what most people will use, therefore avoiding duplication
> > (most of the board files will override this setting now). All right,
> > your sane defaults here can be applied, I won't argue.
> 
> I think all I2C chips support 100 kHz, but only selected ones support
> 400 kHz.

Yes, this is correct. And I never argued about this.

But anyway, V3 patch is out, let's cut this discussion short.

Best regards,
Marek Vasut

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-07-10 15:13                         ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-07-10 15:13 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Robert Schwebel,

> On Mon, Jul 09, 2012 at 05:58:22PM +0200, Marek Vasut wrote:
> > > The kernel should work for all users, not only for the majority, so:
> > > Better safe than sorry.
> > > 
> > > Also, defaults should make the system work. Tuning can be done later by
> > > somebody who understands what is needed.
> > > 
> > > And frankly, this attitude which made you add a potential regression is
> > > worrisome. I'd suggest to give stability a higher priority.
> > 
> > I believe you misunderstood my intention. Setting it to 400kHz was done
> > because it's what most people will use, therefore avoiding duplication
> > (most of the board files will override this setting now). All right,
> > your sane defaults here can be applied, I won't argue.
> 
> I think all I2C chips support 100 kHz, but only selected ones support
> 400 kHz.

Yes, this is correct. And I never argued about this.

But anyway, V3 patch is out, let's cut this discussion short.

Best regards,
Marek Vasut

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-06-09 12:46             ` Shubhrajyoti Datta
@ 2012-06-09 13:10                 ` Marek Vasut
  -1 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-09 13:10 UTC (permalink / raw)
  To: Shubhrajyoti Datta
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Detlev Zundel, Dong Aisheng,
	Fabio Estevam, Linux ARM kernel, Sascha Hauer, Shawn Guo,
	Stefano Babic, Uwe Kleine-König, Wolfgang Denk,
	Wolfram Sang

Dear Shubhrajyoti Datta,

> >> > +struct mxs_i2c_speed_config {
> >> > +       uint32_t        timing0;
> >> > +       uint32_t        timing1;
> >> > +       uint32_t        timing2;
> >> > +};
> >> > +
> >> > +const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
> >> 
> >> You are using 95k?
> > 
> > Yes
> > 
> >> Didnt understand this.
> > 
> > What exactly, it's running (according to the datasheet) at 95kHz.
> 
> Did you intend 100k?

I intended to stick with the datasheet, if you manage to find explanation for 
why they chose 95kHz, I'd be interested to hear it ... btw. 24MHz/95kHz gives 
pretty weird divider, which is quite suspicious.

> and approximating due to clock ... or some other limitaion?

Doesn't seem to be the case, see "btw" part above.

> That is what I was trying to understand.
> 
> >> > +       .timing0        = 0x00780030,
> >> > +       .timing1        = 0x00800030,
> >> > +       .timing2        = 0x0015000d,
> >> > +};

Best regards,
Marek Vasut

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-09 13:10                 ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-09 13:10 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Shubhrajyoti Datta,

> >> > +struct mxs_i2c_speed_config {
> >> > +       uint32_t        timing0;
> >> > +       uint32_t        timing1;
> >> > +       uint32_t        timing2;
> >> > +};
> >> > +
> >> > +const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
> >> 
> >> You are using 95k?
> > 
> > Yes
> > 
> >> Didnt understand this.
> > 
> > What exactly, it's running (according to the datasheet) at 95kHz.
> 
> Did you intend 100k?

I intended to stick with the datasheet, if you manage to find explanation for 
why they chose 95kHz, I'd be interested to hear it ... btw. 24MHz/95kHz gives 
pretty weird divider, which is quite suspicious.

> and approximating due to clock ... or some other limitaion?

Doesn't seem to be the case, see "btw" part above.

> That is what I was trying to understand.
> 
> >> > +       .timing0        = 0x00780030,
> >> > +       .timing1        = 0x00800030,
> >> > +       .timing2        = 0x0015000d,
> >> > +};

Best regards,
Marek Vasut

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-06-09 10:34         ` Marek Vasut
@ 2012-06-09 12:46             ` Shubhrajyoti Datta
  -1 siblings, 0 replies; 34+ messages in thread
From: Shubhrajyoti Datta @ 2012-06-09 12:46 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Detlev Zundel, Dong Aisheng,
	Fabio Estevam, Linux ARM kernel, Sascha Hauer, Shawn Guo,
	Stefano Babic, Uwe Kleine-König, Wolfgang Denk,
	Wolfram Sang

>> >
>> > +struct mxs_i2c_speed_config {
>> > +       uint32_t        timing0;
>> > +       uint32_t        timing1;
>> > +       uint32_t        timing2;
>> > +};
>> > +
>> > +const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
>>
>> You are using 95k?
>
> Yes
>
>> Didnt understand this.
>
> What exactly, it's running (according to the datasheet) at 95kHz.

Did you intend 100k?
and approximating due to clock ... or some other limitaion?

That is what I was trying to understand.
>
>> > +       .timing0        = 0x00780030,
>> > +       .timing1        = 0x00800030,
>> > +       .timing2        = 0x0015000d,
>> > +};

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-09 12:46             ` Shubhrajyoti Datta
  0 siblings, 0 replies; 34+ messages in thread
From: Shubhrajyoti Datta @ 2012-06-09 12:46 UTC (permalink / raw)
  To: linux-arm-kernel

>> >
>> > +struct mxs_i2c_speed_config {
>> > + ? ? ? uint32_t ? ? ? ?timing0;
>> > + ? ? ? uint32_t ? ? ? ?timing1;
>> > + ? ? ? uint32_t ? ? ? ?timing2;
>> > +};
>> > +
>> > +const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
>>
>> You are using 95k?
>
> Yes
>
>> Didnt understand this.
>
> What exactly, it's running (according to the datasheet) at 95kHz.

Did you intend 100k?
and approximating due to clock ... or some other limitaion?

That is what I was trying to understand.
>
>> > + ? ? ? .timing0 ? ? ? ?= 0x00780030,
>> > + ? ? ? .timing1 ? ? ? ?= 0x00800030,
>> > + ? ? ? .timing2 ? ? ? ?= 0x0015000d,
>> > +};

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-06-09 11:25                     ` Sascha Hauer
@ 2012-06-09 11:40                         ` Marek Vasut
  -1 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-09 11:40 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Shubhrajyoti Datta, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	Detlev Zundel, Dong Aisheng, Fabio Estevam, Linux ARM kernel,
	Shawn Guo, Stefano Babic, Uwe Kleine-König, Wolfgang Denk,
	Wolfram Sang

Dear Sascha Hauer,

> On Sat, Jun 09, 2012 at 01:11:42PM +0200, Marek Vasut wrote:
> > Dear Sascha Hauer,
> > 
> > > On Sat, Jun 09, 2012 at 12:34:47PM +0200, Marek Vasut wrote:
> > > > Dear Shubhrajyoti Datta,
> > > > 
> > > > > Didnt understand this.
> > > > 
> > > > What exactly, it's running (according to the datasheet) at 95kHz.
> > > > 
> > > > > > +       .timing0        = 0x00780030,
> > > > > > +       .timing1        = 0x00800030,
> > > > > > +       .timing2        = 0x0015000d,
> > > > > > +};
> > > > > > +
> > > > > > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > > > > > +       .timing0        = 0x000f0007,
> > > > > > +       .timing1        = 0x001f000f,
> > > > > > +       .timing2        = 0x0015000d,
> > > > > > +};
> > > > > > +
> > > > > 
> > > > > How are these values calculated?
> > > > 
> > > > They're not calculated, they're presented in the datasheet. There's
> > > > no formula, even though I believe one could be derived given enough
> > > > effort.
> > > 
> > > Don't these values depend on the input clock of this unit? I don't
> > > know, just asking.
> > 
> > Isn't the i2c block supplied from 24MHz clock source in the mx28?
> 
> Maybe. Shouldn't this be checked then or at least mentioned that these
> values assume a certain clock frequency?

27.5.2 - 27.5.4 in the MX28 TRM -- these values are for 24MHz clock indeed.

> I wonder that currently the timing registers are not initialized at all.
> Do they depend on reset defaults or bootloader setup?

They're set to default values in our case -- I dunno if your bootloader always 
sets them up differently.

> Sascha

Best regards,
Marek Vasut

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-09 11:40                         ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-09 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Sascha Hauer,

> On Sat, Jun 09, 2012 at 01:11:42PM +0200, Marek Vasut wrote:
> > Dear Sascha Hauer,
> > 
> > > On Sat, Jun 09, 2012 at 12:34:47PM +0200, Marek Vasut wrote:
> > > > Dear Shubhrajyoti Datta,
> > > > 
> > > > > Didnt understand this.
> > > > 
> > > > What exactly, it's running (according to the datasheet) at 95kHz.
> > > > 
> > > > > > +       .timing0        = 0x00780030,
> > > > > > +       .timing1        = 0x00800030,
> > > > > > +       .timing2        = 0x0015000d,
> > > > > > +};
> > > > > > +
> > > > > > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > > > > > +       .timing0        = 0x000f0007,
> > > > > > +       .timing1        = 0x001f000f,
> > > > > > +       .timing2        = 0x0015000d,
> > > > > > +};
> > > > > > +
> > > > > 
> > > > > How are these values calculated?
> > > > 
> > > > They're not calculated, they're presented in the datasheet. There's
> > > > no formula, even though I believe one could be derived given enough
> > > > effort.
> > > 
> > > Don't these values depend on the input clock of this unit? I don't
> > > know, just asking.
> > 
> > Isn't the i2c block supplied from 24MHz clock source in the mx28?
> 
> Maybe. Shouldn't this be checked then or at least mentioned that these
> values assume a certain clock frequency?

27.5.2 - 27.5.4 in the MX28 TRM -- these values are for 24MHz clock indeed.

> I wonder that currently the timing registers are not initialized at all.
> Do they depend on reset defaults or bootloader setup?

They're set to default values in our case -- I dunno if your bootloader always 
sets them up differently.

> Sascha

Best regards,
Marek Vasut

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-06-09 11:11                 ` Marek Vasut
@ 2012-06-09 11:25                     ` Sascha Hauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Sascha Hauer @ 2012-06-09 11:25 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Shubhrajyoti Datta, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	Detlev Zundel, Dong Aisheng, Fabio Estevam, Linux ARM kernel,
	Shawn Guo, Stefano Babic, Uwe Kleine-König, Wolfgang Denk,
	Wolfram Sang

On Sat, Jun 09, 2012 at 01:11:42PM +0200, Marek Vasut wrote:
> Dear Sascha Hauer,
> 
> > On Sat, Jun 09, 2012 at 12:34:47PM +0200, Marek Vasut wrote:
> > > Dear Shubhrajyoti Datta,
> > > 
> > > > Didnt understand this.
> > > 
> > > What exactly, it's running (according to the datasheet) at 95kHz.
> > > 
> > > > > +       .timing0        = 0x00780030,
> > > > > +       .timing1        = 0x00800030,
> > > > > +       .timing2        = 0x0015000d,
> > > > > +};
> > > > > +
> > > > > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > > > > +       .timing0        = 0x000f0007,
> > > > > +       .timing1        = 0x001f000f,
> > > > > +       .timing2        = 0x0015000d,
> > > > > +};
> > > > > +
> > > > 
> > > > How are these values calculated?
> > > 
> > > They're not calculated, they're presented in the datasheet. There's no
> > > formula, even though I believe one could be derived given enough effort.
> > 
> > Don't these values depend on the input clock of this unit? I don't know,
> > just asking.
> 
> Isn't the i2c block supplied from 24MHz clock source in the mx28?

Maybe. Shouldn't this be checked then or at least mentioned that these
values assume a certain clock frequency?

I wonder that currently the timing registers are not initialized at all.
Do they depend on reset defaults or bootloader setup?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-09 11:25                     ` Sascha Hauer
  0 siblings, 0 replies; 34+ messages in thread
From: Sascha Hauer @ 2012-06-09 11:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 09, 2012 at 01:11:42PM +0200, Marek Vasut wrote:
> Dear Sascha Hauer,
> 
> > On Sat, Jun 09, 2012 at 12:34:47PM +0200, Marek Vasut wrote:
> > > Dear Shubhrajyoti Datta,
> > > 
> > > > Didnt understand this.
> > > 
> > > What exactly, it's running (according to the datasheet) at 95kHz.
> > > 
> > > > > +       .timing0        = 0x00780030,
> > > > > +       .timing1        = 0x00800030,
> > > > > +       .timing2        = 0x0015000d,
> > > > > +};
> > > > > +
> > > > > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > > > > +       .timing0        = 0x000f0007,
> > > > > +       .timing1        = 0x001f000f,
> > > > > +       .timing2        = 0x0015000d,
> > > > > +};
> > > > > +
> > > > 
> > > > How are these values calculated?
> > > 
> > > They're not calculated, they're presented in the datasheet. There's no
> > > formula, even though I believe one could be derived given enough effort.
> > 
> > Don't these values depend on the input clock of this unit? I don't know,
> > just asking.
> 
> Isn't the i2c block supplied from 24MHz clock source in the mx28?

Maybe. Shouldn't this be checked then or at least mentioned that these
values assume a certain clock frequency?

I wonder that currently the timing registers are not initialized at all.
Do they depend on reset defaults or bootloader setup?

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-06-09 10:53             ` Sascha Hauer
@ 2012-06-09 11:11                 ` Marek Vasut
  -1 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-09 11:11 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Shubhrajyoti Datta, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	Detlev Zundel, Dong Aisheng, Fabio Estevam, Linux ARM kernel,
	Shawn Guo, Stefano Babic, Uwe Kleine-König, Wolfgang Denk,
	Wolfram Sang

Dear Sascha Hauer,

> On Sat, Jun 09, 2012 at 12:34:47PM +0200, Marek Vasut wrote:
> > Dear Shubhrajyoti Datta,
> > 
> > > Didnt understand this.
> > 
> > What exactly, it's running (according to the datasheet) at 95kHz.
> > 
> > > > +       .timing0        = 0x00780030,
> > > > +       .timing1        = 0x00800030,
> > > > +       .timing2        = 0x0015000d,
> > > > +};
> > > > +
> > > > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > > > +       .timing0        = 0x000f0007,
> > > > +       .timing1        = 0x001f000f,
> > > > +       .timing2        = 0x0015000d,
> > > > +};
> > > > +
> > > 
> > > How are these values calculated?
> > 
> > They're not calculated, they're presented in the datasheet. There's no
> > formula, even though I believe one could be derived given enough effort.
> 
> Don't these values depend on the input clock of this unit? I don't know,
> just asking.

Isn't the i2c block supplied from 24MHz clock source in the mx28?

> Sascha

Best regards,
Marek Vasut

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-09 11:11                 ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-09 11:11 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Sascha Hauer,

> On Sat, Jun 09, 2012 at 12:34:47PM +0200, Marek Vasut wrote:
> > Dear Shubhrajyoti Datta,
> > 
> > > Didnt understand this.
> > 
> > What exactly, it's running (according to the datasheet) at 95kHz.
> > 
> > > > +       .timing0        = 0x00780030,
> > > > +       .timing1        = 0x00800030,
> > > > +       .timing2        = 0x0015000d,
> > > > +};
> > > > +
> > > > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > > > +       .timing0        = 0x000f0007,
> > > > +       .timing1        = 0x001f000f,
> > > > +       .timing2        = 0x0015000d,
> > > > +};
> > > > +
> > > 
> > > How are these values calculated?
> > 
> > They're not calculated, they're presented in the datasheet. There's no
> > formula, even though I believe one could be derived given enough effort.
> 
> Don't these values depend on the input clock of this unit? I don't know,
> just asking.

Isn't the i2c block supplied from 24MHz clock source in the mx28?

> Sascha

Best regards,
Marek Vasut

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-06-09 10:34         ` Marek Vasut
@ 2012-06-09 10:53             ` Sascha Hauer
  -1 siblings, 0 replies; 34+ messages in thread
From: Sascha Hauer @ 2012-06-09 10:53 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Shubhrajyoti Datta, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	Detlev Zundel, Dong Aisheng, Fabio Estevam, Linux ARM kernel,
	Shawn Guo, Stefano Babic, Uwe Kleine-König, Wolfgang Denk,
	Wolfram Sang

On Sat, Jun 09, 2012 at 12:34:47PM +0200, Marek Vasut wrote:
> Dear Shubhrajyoti Datta,
> 
> 
> > Didnt understand this.
> 
> What exactly, it's running (according to the datasheet) at 95kHz.
> 
> > > +       .timing0        = 0x00780030,
> > > +       .timing1        = 0x00800030,
> > > +       .timing2        = 0x0015000d,
> > > +};
> > > +
> > > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > > +       .timing0        = 0x000f0007,
> > > +       .timing1        = 0x001f000f,
> > > +       .timing2        = 0x0015000d,
> > > +};
> > > +
> > 
> > How are these values calculated?
> 
> They're not calculated, they're presented in the datasheet. There's no formula, 
> even though I believe one could be derived given enough effort.

Don't these values depend on the input clock of this unit? I don't know,
just asking.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-09 10:53             ` Sascha Hauer
  0 siblings, 0 replies; 34+ messages in thread
From: Sascha Hauer @ 2012-06-09 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 09, 2012 at 12:34:47PM +0200, Marek Vasut wrote:
> Dear Shubhrajyoti Datta,
> 
> 
> > Didnt understand this.
> 
> What exactly, it's running (according to the datasheet) at 95kHz.
> 
> > > +       .timing0        = 0x00780030,
> > > +       .timing1        = 0x00800030,
> > > +       .timing2        = 0x0015000d,
> > > +};
> > > +
> > > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > > +       .timing0        = 0x000f0007,
> > > +       .timing1        = 0x001f000f,
> > > +       .timing2        = 0x0015000d,
> > > +};
> > > +
> > 
> > How are these values calculated?
> 
> They're not calculated, they're presented in the datasheet. There's no formula, 
> even though I believe one could be derived given enough effort.

Don't these values depend on the input clock of this unit? I don't know,
just asking.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-06-09  4:15     ` Shubhrajyoti Datta
@ 2012-06-09 10:34         ` Marek Vasut
  -1 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-09 10:34 UTC (permalink / raw)
  To: Shubhrajyoti Datta
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Detlev Zundel, Dong Aisheng,
	Fabio Estevam, Linux ARM kernel, Sascha Hauer, Shawn Guo,
	Stefano Babic, Uwe Kleine-König, Wolfgang Denk,
	Wolfram Sang

Dear Shubhrajyoti Datta,

> On Sat, Jun 9, 2012 at 12:24 AM, Marek Vasut <marex-ynQEQJNshbs@public.gmane.org> wrote:
> > This patch configures the I2C bus timing registers according
> > to information passed via DT. Currently, 100kHz and 400kHz
> > modes are supported.
> > 
> > Signed-off-by: Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>
> > Cc: Detlev Zundel <dzu-ynQEQJNshbs@public.gmane.org>
> > CC: Dong Aisheng <b29396-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> > CC: Fabio Estevam <fabio.estevam-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> > Cc: Linux ARM kernel <linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
> > Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > CC: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > CC: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > Cc: Stefano Babic <sbabic-ynQEQJNshbs@public.gmane.org>
> > CC: Uwe Kleine-König <u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > Cc: Wolfgang Denk <wd-ynQEQJNshbs@public.gmane.org>
> > Cc: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> > ---
> >  Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    1 +
> >  arch/arm/boot/dts/imx28.dtsi                      |    2 +
> >  drivers/i2c/busses/i2c-mxs.c                      |   54
> > +++++++++++++++++++++ 3 files changed, 57 insertions(+)
> > 
> > V2: Use clock-frequency instead
> > 
> > diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> > b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt index
> > 1bfc02d..d2bf750 100644
> > --- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> > +++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> > @@ -4,6 +4,7 @@ Required properties:
> >  - compatible: Should be "fsl,<chip>-i2c"
> >  - reg: Should contain registers location and length
> >  - interrupts: Should contain ERROR and DMA interrupts
> > +- clock-frequency: desired I2C bus clock frequency in Hz.
> > 
> >  Examples:
> > 
> > diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> > index a89da5a..714e63c 100644
> > --- a/arch/arm/boot/dts/imx28.dtsi
> > +++ b/arch/arm/boot/dts/imx28.dtsi
> > @@ -398,6 +398,7 @@
> >                                compatible = "fsl,imx28-i2c";
> >                                reg = <0x80058000 2000>;
> >                                interrupts = <111 68>;
> > +                               clock-frequency = <400000>;
> >                                status = "disabled";
> >                        };
> > 
> > @@ -407,6 +408,7 @@
> >                                compatible = "fsl,imx28-i2c";
> >                                reg = <0x8005a000 2000>;
> >                                interrupts = <110 69>;
> > +                               clock-frequency = <400000>;
> >                                status = "disabled";
> >                        };
> > 
> > diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
> > index 04eb441..b4d083f 100644
> > --- a/drivers/i2c/busses/i2c-mxs.c
> > +++ b/drivers/i2c/busses/i2c-mxs.c
> > @@ -46,6 +46,10 @@
> >  #define MXS_I2C_CTRL0_DIRECTION                        0x00010000
> >  #define MXS_I2C_CTRL0_XFER_COUNT(v)            ((v) & 0x0000FFFF)
> > 
> > +#define MXS_I2C_TIMING0                (0x10)
> > +#define MXS_I2C_TIMING1                (0x20)
> > +#define MXS_I2C_TIMING2                (0x30)
> > +
> >  #define MXS_I2C_CTRL1          (0x40)
> >  #define MXS_I2C_CTRL1_SET      (0x44)
> >  #define MXS_I2C_CTRL1_CLR      (0x48)
> > @@ -97,6 +101,24 @@
> >  #define MXS_CMD_I2C_READ       (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
> >                                 MXS_I2C_CTRL0_MASTER_MODE)
> > 
> > +struct mxs_i2c_speed_config {
> > +       uint32_t        timing0;
> > +       uint32_t        timing1;
> > +       uint32_t        timing2;
> > +};
> > +
> > +const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
> 
> You are using 95k?

Yes

> Didnt understand this.

What exactly, it's running (according to the datasheet) at 95kHz.

> > +       .timing0        = 0x00780030,
> > +       .timing1        = 0x00800030,
> > +       .timing2        = 0x0015000d,
> > +};
> > +
> > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > +       .timing0        = 0x000f0007,
> > +       .timing1        = 0x001f000f,
> > +       .timing2        = 0x0015000d,
> > +};
> > +
> 
> How are these values calculated?

They're not calculated, they're presented in the datasheet. There's no formula, 
even though I believe one could be derived given enough effort.

Best regards,
Marek Vasut

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-09 10:34         ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-09 10:34 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Shubhrajyoti Datta,

> On Sat, Jun 9, 2012 at 12:24 AM, Marek Vasut <marex@denx.de> wrote:
> > This patch configures the I2C bus timing registers according
> > to information passed via DT. Currently, 100kHz and 400kHz
> > modes are supported.
> > 
> > Signed-off-by: Marek Vasut <marex@denx.de>
> > Cc: Detlev Zundel <dzu@denx.de>
> > CC: Dong Aisheng <b29396@freescale.com>
> > CC: Fabio Estevam <fabio.estevam@freescale.com>
> > Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
> > Cc: linux-i2c at vger.kernel.org
> > CC: Sascha Hauer <s.hauer@pengutronix.de>
> > CC: Shawn Guo <shawn.guo@linaro.org>
> > Cc: Stefano Babic <sbabic@denx.de>
> > CC: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> > Cc: Wolfgang Denk <wd@denx.de>
> > Cc: Wolfram Sang <w.sang@pengutronix.de>
> > ---
> >  Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    1 +
> >  arch/arm/boot/dts/imx28.dtsi                      |    2 +
> >  drivers/i2c/busses/i2c-mxs.c                      |   54
> > +++++++++++++++++++++ 3 files changed, 57 insertions(+)
> > 
> > V2: Use clock-frequency instead
> > 
> > diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> > b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt index
> > 1bfc02d..d2bf750 100644
> > --- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> > +++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> > @@ -4,6 +4,7 @@ Required properties:
> >  - compatible: Should be "fsl,<chip>-i2c"
> >  - reg: Should contain registers location and length
> >  - interrupts: Should contain ERROR and DMA interrupts
> > +- clock-frequency: desired I2C bus clock frequency in Hz.
> > 
> >  Examples:
> > 
> > diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> > index a89da5a..714e63c 100644
> > --- a/arch/arm/boot/dts/imx28.dtsi
> > +++ b/arch/arm/boot/dts/imx28.dtsi
> > @@ -398,6 +398,7 @@
> >                                compatible = "fsl,imx28-i2c";
> >                                reg = <0x80058000 2000>;
> >                                interrupts = <111 68>;
> > +                               clock-frequency = <400000>;
> >                                status = "disabled";
> >                        };
> > 
> > @@ -407,6 +408,7 @@
> >                                compatible = "fsl,imx28-i2c";
> >                                reg = <0x8005a000 2000>;
> >                                interrupts = <110 69>;
> > +                               clock-frequency = <400000>;
> >                                status = "disabled";
> >                        };
> > 
> > diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
> > index 04eb441..b4d083f 100644
> > --- a/drivers/i2c/busses/i2c-mxs.c
> > +++ b/drivers/i2c/busses/i2c-mxs.c
> > @@ -46,6 +46,10 @@
> >  #define MXS_I2C_CTRL0_DIRECTION                        0x00010000
> >  #define MXS_I2C_CTRL0_XFER_COUNT(v)            ((v) & 0x0000FFFF)
> > 
> > +#define MXS_I2C_TIMING0                (0x10)
> > +#define MXS_I2C_TIMING1                (0x20)
> > +#define MXS_I2C_TIMING2                (0x30)
> > +
> >  #define MXS_I2C_CTRL1          (0x40)
> >  #define MXS_I2C_CTRL1_SET      (0x44)
> >  #define MXS_I2C_CTRL1_CLR      (0x48)
> > @@ -97,6 +101,24 @@
> >  #define MXS_CMD_I2C_READ       (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
> >                                 MXS_I2C_CTRL0_MASTER_MODE)
> > 
> > +struct mxs_i2c_speed_config {
> > +       uint32_t        timing0;
> > +       uint32_t        timing1;
> > +       uint32_t        timing2;
> > +};
> > +
> > +const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
> 
> You are using 95k?

Yes

> Didnt understand this.

What exactly, it's running (according to the datasheet) at 95kHz.

> > +       .timing0        = 0x00780030,
> > +       .timing1        = 0x00800030,
> > +       .timing2        = 0x0015000d,
> > +};
> > +
> > +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> > +       .timing0        = 0x000f0007,
> > +       .timing1        = 0x001f000f,
> > +       .timing2        = 0x0015000d,
> > +};
> > +
> 
> How are these values calculated?

They're not calculated, they're presented in the datasheet. There's no formula, 
even though I believe one could be derived given enough effort.

Best regards,
Marek Vasut

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

* Re: [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
  2012-06-08 18:54 ` Marek Vasut
@ 2012-06-09  4:15     ` Shubhrajyoti Datta
  -1 siblings, 0 replies; 34+ messages in thread
From: Shubhrajyoti Datta @ 2012-06-09  4:15 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Detlev Zundel, Dong Aisheng,
	Fabio Estevam, Linux ARM kernel, Sascha Hauer, Shawn Guo,
	Stefano Babic, Uwe Kleine-König, Wolfgang Denk,
	Wolfram Sang

On Sat, Jun 9, 2012 at 12:24 AM, Marek Vasut <marex-ynQEQJNshbs@public.gmane.org> wrote:
> This patch configures the I2C bus timing registers according
> to information passed via DT. Currently, 100kHz and 400kHz
> modes are supported.
>
> Signed-off-by: Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>
> Cc: Detlev Zundel <dzu-ynQEQJNshbs@public.gmane.org>
> CC: Dong Aisheng <b29396-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> CC: Fabio Estevam <fabio.estevam-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> Cc: Linux ARM kernel <linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
> Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> CC: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> CC: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Stefano Babic <sbabic-ynQEQJNshbs@public.gmane.org>
> CC: Uwe Kleine-König <u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Cc: Wolfgang Denk <wd-ynQEQJNshbs@public.gmane.org>
> Cc: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    1 +
>  arch/arm/boot/dts/imx28.dtsi                      |    2 +
>  drivers/i2c/busses/i2c-mxs.c                      |   54 +++++++++++++++++++++
>  3 files changed, 57 insertions(+)
>
> V2: Use clock-frequency instead
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> index 1bfc02d..d2bf750 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> @@ -4,6 +4,7 @@ Required properties:
>  - compatible: Should be "fsl,<chip>-i2c"
>  - reg: Should contain registers location and length
>  - interrupts: Should contain ERROR and DMA interrupts
> +- clock-frequency: desired I2C bus clock frequency in Hz.
>
>  Examples:
>
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index a89da5a..714e63c 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -398,6 +398,7 @@
>                                compatible = "fsl,imx28-i2c";
>                                reg = <0x80058000 2000>;
>                                interrupts = <111 68>;
> +                               clock-frequency = <400000>;
>                                status = "disabled";
>                        };
>
> @@ -407,6 +408,7 @@
>                                compatible = "fsl,imx28-i2c";
>                                reg = <0x8005a000 2000>;
>                                interrupts = <110 69>;
> +                               clock-frequency = <400000>;
>                                status = "disabled";
>                        };
>
> diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
> index 04eb441..b4d083f 100644
> --- a/drivers/i2c/busses/i2c-mxs.c
> +++ b/drivers/i2c/busses/i2c-mxs.c
> @@ -46,6 +46,10 @@
>  #define MXS_I2C_CTRL0_DIRECTION                        0x00010000
>  #define MXS_I2C_CTRL0_XFER_COUNT(v)            ((v) & 0x0000FFFF)
>
> +#define MXS_I2C_TIMING0                (0x10)
> +#define MXS_I2C_TIMING1                (0x20)
> +#define MXS_I2C_TIMING2                (0x30)
> +
>  #define MXS_I2C_CTRL1          (0x40)
>  #define MXS_I2C_CTRL1_SET      (0x44)
>  #define MXS_I2C_CTRL1_CLR      (0x48)
> @@ -97,6 +101,24 @@
>  #define MXS_CMD_I2C_READ       (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
>                                 MXS_I2C_CTRL0_MASTER_MODE)
>
> +struct mxs_i2c_speed_config {
> +       uint32_t        timing0;
> +       uint32_t        timing1;
> +       uint32_t        timing2;
> +};
> +
> +const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
You are using 95k?
Didnt understand this.


> +       .timing0        = 0x00780030,
> +       .timing1        = 0x00800030,
> +       .timing2        = 0x0015000d,
> +};
> +
> +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> +       .timing0        = 0x000f0007,
> +       .timing1        = 0x001f000f,
> +       .timing2        = 0x0015000d,
> +};
> +

How are these values calculated?

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-09  4:15     ` Shubhrajyoti Datta
  0 siblings, 0 replies; 34+ messages in thread
From: Shubhrajyoti Datta @ 2012-06-09  4:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 9, 2012 at 12:24 AM, Marek Vasut <marex@denx.de> wrote:
> This patch configures the I2C bus timing registers according
> to information passed via DT. Currently, 100kHz and 400kHz
> modes are supported.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> CC: Dong Aisheng <b29396@freescale.com>
> CC: Fabio Estevam <fabio.estevam@freescale.com>
> Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
> Cc: linux-i2c at vger.kernel.org
> CC: Sascha Hauer <s.hauer@pengutronix.de>
> CC: Shawn Guo <shawn.guo@linaro.org>
> Cc: Stefano Babic <sbabic@denx.de>
> CC: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Wolfram Sang <w.sang@pengutronix.de>
> ---
> ?Documentation/devicetree/bindings/i2c/i2c-mxs.txt | ? ?1 +
> ?arch/arm/boot/dts/imx28.dtsi ? ? ? ? ? ? ? ? ? ? ?| ? ?2 +
> ?drivers/i2c/busses/i2c-mxs.c ? ? ? ? ? ? ? ? ? ? ?| ? 54 +++++++++++++++++++++
> ?3 files changed, 57 insertions(+)
>
> V2: Use clock-frequency instead
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> index 1bfc02d..d2bf750 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
> @@ -4,6 +4,7 @@ Required properties:
> ?- compatible: Should be "fsl,<chip>-i2c"
> ?- reg: Should contain registers location and length
> ?- interrupts: Should contain ERROR and DMA interrupts
> +- clock-frequency: desired I2C bus clock frequency in Hz.
>
> ?Examples:
>
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index a89da5a..714e63c 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -398,6 +398,7 @@
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?compatible = "fsl,imx28-i2c";
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?reg = <0x80058000 2000>;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?interrupts = <111 68>;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clock-frequency = <400000>;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?status = "disabled";
> ? ? ? ? ? ? ? ? ? ? ? ?};
>
> @@ -407,6 +408,7 @@
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?compatible = "fsl,imx28-i2c";
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?reg = <0x8005a000 2000>;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?interrupts = <110 69>;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clock-frequency = <400000>;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?status = "disabled";
> ? ? ? ? ? ? ? ? ? ? ? ?};
>
> diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
> index 04eb441..b4d083f 100644
> --- a/drivers/i2c/busses/i2c-mxs.c
> +++ b/drivers/i2c/busses/i2c-mxs.c
> @@ -46,6 +46,10 @@
> ?#define MXS_I2C_CTRL0_DIRECTION ? ? ? ? ? ? ? ? ? ? ? ?0x00010000
> ?#define MXS_I2C_CTRL0_XFER_COUNT(v) ? ? ? ? ? ?((v) & 0x0000FFFF)
>
> +#define MXS_I2C_TIMING0 ? ? ? ? ? ? ? ?(0x10)
> +#define MXS_I2C_TIMING1 ? ? ? ? ? ? ? ?(0x20)
> +#define MXS_I2C_TIMING2 ? ? ? ? ? ? ? ?(0x30)
> +
> ?#define MXS_I2C_CTRL1 ? ? ? ? ?(0x40)
> ?#define MXS_I2C_CTRL1_SET ? ? ?(0x44)
> ?#define MXS_I2C_CTRL1_CLR ? ? ?(0x48)
> @@ -97,6 +101,24 @@
> ?#define MXS_CMD_I2C_READ ? ? ? (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MXS_I2C_CTRL0_MASTER_MODE)
>
> +struct mxs_i2c_speed_config {
> + ? ? ? uint32_t ? ? ? ?timing0;
> + ? ? ? uint32_t ? ? ? ?timing1;
> + ? ? ? uint32_t ? ? ? ?timing2;
> +};
> +
> +const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
You are using 95k?
Didnt understand this.


> + ? ? ? .timing0 ? ? ? ?= 0x00780030,
> + ? ? ? .timing1 ? ? ? ?= 0x00800030,
> + ? ? ? .timing2 ? ? ? ?= 0x0015000d,
> +};
> +
> +const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
> + ? ? ? .timing0 ? ? ? ?= 0x000f0007,
> + ? ? ? .timing1 ? ? ? ?= 0x001f000f,
> + ? ? ? .timing2 ? ? ? ?= 0x0015000d,
> +};
> +

How are these values calculated?

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-08 18:54 ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-08 18:54 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA
  Cc: Marek Vasut, Detlev Zundel, Dong Aisheng, Fabio Estevam,
	Linux ARM kernel, Sascha Hauer, Shawn Guo, Stefano Babic,
	Uwe Kleine-König, Wolfgang Denk, Wolfram Sang

This patch configures the I2C bus timing registers according
to information passed via DT. Currently, 100kHz and 400kHz
modes are supported.

Signed-off-by: Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>
Cc: Detlev Zundel <dzu-ynQEQJNshbs@public.gmane.org>
CC: Dong Aisheng <b29396-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
CC: Fabio Estevam <fabio.estevam-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Cc: Linux ARM kernel <linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
CC: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Stefano Babic <sbabic-ynQEQJNshbs@public.gmane.org>
CC: Uwe Kleine-König <u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Cc: Wolfgang Denk <wd-ynQEQJNshbs@public.gmane.org>
Cc: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    1 +
 arch/arm/boot/dts/imx28.dtsi                      |    2 +
 drivers/i2c/busses/i2c-mxs.c                      |   54 +++++++++++++++++++++
 3 files changed, 57 insertions(+)

V2: Use clock-frequency instead

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
index 1bfc02d..d2bf750 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
@@ -4,6 +4,7 @@ Required properties:
 - compatible: Should be "fsl,<chip>-i2c"
 - reg: Should contain registers location and length
 - interrupts: Should contain ERROR and DMA interrupts
+- clock-frequency: desired I2C bus clock frequency in Hz.
 
 Examples:
 
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index a89da5a..714e63c 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -398,6 +398,7 @@
 				compatible = "fsl,imx28-i2c";
 				reg = <0x80058000 2000>;
 				interrupts = <111 68>;
+				clock-frequency = <400000>;
 				status = "disabled";
 			};
 
@@ -407,6 +408,7 @@
 				compatible = "fsl,imx28-i2c";
 				reg = <0x8005a000 2000>;
 				interrupts = <110 69>;
+				clock-frequency = <400000>;
 				status = "disabled";
 			};
 
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 04eb441..b4d083f 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -46,6 +46,10 @@
 #define MXS_I2C_CTRL0_DIRECTION			0x00010000
 #define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
 
+#define MXS_I2C_TIMING0		(0x10)
+#define MXS_I2C_TIMING1		(0x20)
+#define MXS_I2C_TIMING2		(0x30)
+
 #define MXS_I2C_CTRL1		(0x40)
 #define MXS_I2C_CTRL1_SET	(0x44)
 #define MXS_I2C_CTRL1_CLR	(0x48)
@@ -97,6 +101,24 @@
 #define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
 				 MXS_I2C_CTRL0_MASTER_MODE)
 
+struct mxs_i2c_speed_config {
+	uint32_t	timing0;
+	uint32_t	timing1;
+	uint32_t	timing2;
+};
+
+const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
+	.timing0	= 0x00780030,
+	.timing1	= 0x00800030,
+	.timing2	= 0x0015000d,
+};
+
+const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
+	.timing0	= 0x000f0007,
+	.timing1	= 0x001f000f,
+	.timing2	= 0x0015000d,
+};
+
 /**
  * struct mxs_i2c_dev - per device, private MXS-I2C data
  *
@@ -112,11 +134,17 @@ struct mxs_i2c_dev {
 	struct completion cmd_complete;
 	u32 cmd_err;
 	struct i2c_adapter adapter;
+	const struct mxs_i2c_speed_config *speed;
 };
 
 static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
 {
 	stmp_reset_block(i2c->regs);
+
+	writel(i2c->speed->timing0, i2c->regs + MXS_I2C_TIMING0);
+	writel(i2c->speed->timing1, i2c->regs + MXS_I2C_TIMING1);
+	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
+
 	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
 	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
 			i2c->regs + MXS_I2C_QUEUECTRL_SET);
@@ -319,6 +347,27 @@ static const struct i2c_algorithm mxs_i2c_algo = {
 	.functionality = mxs_i2c_func,
 };
 
+static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
+{
+	uint32_t speed;
+	struct device *dev = i2c->dev;
+	struct device_node *node = dev->of_node;
+
+	if (!node)
+		return -EINVAL;
+
+	i2c->speed = &mxs_i2c_95kHz_config;
+	ret = of_property_read_u32(node, "clock-frequency", &speed);
+	if (ret)
+		dev_warn(dev, "No I2C speed selected, using 100kHz\n");
+	else if (speed == 400000)
+		i2c->speed = &mxs_i2c_400kHz_config;
+	else if (speed != 100000)
+		dev_warn(dev, "Invalid I2C speed selected, using 100kHz\n");
+
+	return 0;
+}
+
 static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -358,6 +407,11 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 		return err;
 
 	i2c->dev = dev;
+
+	err = mxs_i2c_get_ofdata(i2c);
+	if (err)
+		return err;
+
 	platform_set_drvdata(pdev, i2c);
 
 	/* Do reset to enforce correct startup after pinmuxing */
-- 
1.7.10

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

* [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c
@ 2012-06-08 18:54 ` Marek Vasut
  0 siblings, 0 replies; 34+ messages in thread
From: Marek Vasut @ 2012-06-08 18:54 UTC (permalink / raw)
  To: linux-arm-kernel

This patch configures the I2C bus timing registers according
to information passed via DT. Currently, 100kHz and 400kHz
modes are supported.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
CC: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: linux-i2c at vger.kernel.org
CC: Sascha Hauer <s.hauer@pengutronix.de>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
CC: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Wolfram Sang <w.sang@pengutronix.de>
---
 Documentation/devicetree/bindings/i2c/i2c-mxs.txt |    1 +
 arch/arm/boot/dts/imx28.dtsi                      |    2 +
 drivers/i2c/busses/i2c-mxs.c                      |   54 +++++++++++++++++++++
 3 files changed, 57 insertions(+)

V2: Use clock-frequency instead

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
index 1bfc02d..d2bf750 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt
@@ -4,6 +4,7 @@ Required properties:
 - compatible: Should be "fsl,<chip>-i2c"
 - reg: Should contain registers location and length
 - interrupts: Should contain ERROR and DMA interrupts
+- clock-frequency: desired I2C bus clock frequency in Hz.
 
 Examples:
 
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index a89da5a..714e63c 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -398,6 +398,7 @@
 				compatible = "fsl,imx28-i2c";
 				reg = <0x80058000 2000>;
 				interrupts = <111 68>;
+				clock-frequency = <400000>;
 				status = "disabled";
 			};
 
@@ -407,6 +408,7 @@
 				compatible = "fsl,imx28-i2c";
 				reg = <0x8005a000 2000>;
 				interrupts = <110 69>;
+				clock-frequency = <400000>;
 				status = "disabled";
 			};
 
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 04eb441..b4d083f 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -46,6 +46,10 @@
 #define MXS_I2C_CTRL0_DIRECTION			0x00010000
 #define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
 
+#define MXS_I2C_TIMING0		(0x10)
+#define MXS_I2C_TIMING1		(0x20)
+#define MXS_I2C_TIMING2		(0x30)
+
 #define MXS_I2C_CTRL1		(0x40)
 #define MXS_I2C_CTRL1_SET	(0x44)
 #define MXS_I2C_CTRL1_CLR	(0x48)
@@ -97,6 +101,24 @@
 #define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
 				 MXS_I2C_CTRL0_MASTER_MODE)
 
+struct mxs_i2c_speed_config {
+	uint32_t	timing0;
+	uint32_t	timing1;
+	uint32_t	timing2;
+};
+
+const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {
+	.timing0	= 0x00780030,
+	.timing1	= 0x00800030,
+	.timing2	= 0x0015000d,
+};
+
+const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {
+	.timing0	= 0x000f0007,
+	.timing1	= 0x001f000f,
+	.timing2	= 0x0015000d,
+};
+
 /**
  * struct mxs_i2c_dev - per device, private MXS-I2C data
  *
@@ -112,11 +134,17 @@ struct mxs_i2c_dev {
 	struct completion cmd_complete;
 	u32 cmd_err;
 	struct i2c_adapter adapter;
+	const struct mxs_i2c_speed_config *speed;
 };
 
 static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
 {
 	stmp_reset_block(i2c->regs);
+
+	writel(i2c->speed->timing0, i2c->regs + MXS_I2C_TIMING0);
+	writel(i2c->speed->timing1, i2c->regs + MXS_I2C_TIMING1);
+	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
+
 	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
 	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
 			i2c->regs + MXS_I2C_QUEUECTRL_SET);
@@ -319,6 +347,27 @@ static const struct i2c_algorithm mxs_i2c_algo = {
 	.functionality = mxs_i2c_func,
 };
 
+static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
+{
+	uint32_t speed;
+	struct device *dev = i2c->dev;
+	struct device_node *node = dev->of_node;
+
+	if (!node)
+		return -EINVAL;
+
+	i2c->speed = &mxs_i2c_95kHz_config;
+	ret = of_property_read_u32(node, "clock-frequency", &speed);
+	if (ret)
+		dev_warn(dev, "No I2C speed selected, using 100kHz\n");
+	else if (speed == 400000)
+		i2c->speed = &mxs_i2c_400kHz_config;
+	else if (speed != 100000)
+		dev_warn(dev, "Invalid I2C speed selected, using 100kHz\n");
+
+	return 0;
+}
+
 static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -358,6 +407,11 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
 		return err;
 
 	i2c->dev = dev;
+
+	err = mxs_i2c_get_ofdata(i2c);
+	if (err)
+		return err;
+
 	platform_set_drvdata(pdev, i2c);
 
 	/* Do reset to enforce correct startup after pinmuxing */
-- 
1.7.10

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

end of thread, other threads:[~2012-07-10 15:13 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-06  6:09 [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c Marek Vasut
2012-07-06  6:09 ` Marek Vasut
     [not found] ` <1341554956-17416-1-git-send-email-marex-ynQEQJNshbs@public.gmane.org>
2012-07-06  6:09   ` [PATCH 2/2 V2] MXS: Implement DMA support into mxs-i2c Marek Vasut
2012-07-06  6:09     ` Marek Vasut
2012-07-09 10:53   ` [PATCH 1/2 V2] MXS: Set I2C timing registers for mxs-i2c Wolfram Sang
2012-07-09 10:53     ` Wolfram Sang
     [not found]     ` <20120709105338.GE1296-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-07-09 11:07       ` Marek Vasut
2012-07-09 11:07         ` Marek Vasut
     [not found]         ` <201207091307.35860.marex-ynQEQJNshbs@public.gmane.org>
2012-07-09 12:05           ` Wolfram Sang
2012-07-09 12:05             ` Wolfram Sang
     [not found]             ` <20120709120523.GG1296-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-07-09 15:58               ` Marek Vasut
2012-07-09 15:58                 ` Marek Vasut
     [not found]                 ` <201207091758.22788.marex-ynQEQJNshbs@public.gmane.org>
2012-07-10 14:09                   ` Robert Schwebel
2012-07-10 14:09                     ` Robert Schwebel
     [not found]                     ` <20120710140911.GK20456-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-07-10 15:13                       ` Marek Vasut
2012-07-10 15:13                         ` Marek Vasut
  -- strict thread matches above, loose matches on Subject: below --
2012-06-08 18:54 Marek Vasut
2012-06-08 18:54 ` Marek Vasut
     [not found] ` <1339181689-22573-1-git-send-email-marex-ynQEQJNshbs@public.gmane.org>
2012-06-09  4:15   ` Shubhrajyoti Datta
2012-06-09  4:15     ` Shubhrajyoti Datta
     [not found]     ` <CAM=Q2cuv0NQTYJH=+d6Na+JK5rGYsLiSmuX7g8T-_Ry7bs3fRQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-06-09 10:34       ` Marek Vasut
2012-06-09 10:34         ` Marek Vasut
     [not found]         ` <201206091234.47309.marex-ynQEQJNshbs@public.gmane.org>
2012-06-09 10:53           ` Sascha Hauer
2012-06-09 10:53             ` Sascha Hauer
     [not found]             ` <20120609105330.GF30400-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-06-09 11:11               ` Marek Vasut
2012-06-09 11:11                 ` Marek Vasut
     [not found]                 ` <201206091311.43229.marex-ynQEQJNshbs@public.gmane.org>
2012-06-09 11:25                   ` Sascha Hauer
2012-06-09 11:25                     ` Sascha Hauer
     [not found]                     ` <20120609112545.GH30400-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-06-09 11:40                       ` Marek Vasut
2012-06-09 11:40                         ` Marek Vasut
2012-06-09 12:46           ` Shubhrajyoti Datta
2012-06-09 12:46             ` Shubhrajyoti Datta
     [not found]             ` <CAM=Q2cvvwXimLY358ET69U6qCsGoxenYMNtApYbhpn4cCC0nUg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-06-09 13:10               ` Marek Vasut
2012-06-09 13:10                 ` Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.