linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
@ 2011-11-15 17:54 Jayachandran C.
  2011-11-16 11:12 ` Shubhrajyoti Datta
  0 siblings, 1 reply; 17+ messages in thread
From: Jayachandran C. @ 2011-11-15 17:54 UTC (permalink / raw)
  To: linux-i2c; +Cc: ben-linux, linux-mips, Ganesan Ramalingam, Jayachandran C

From: Ganesan Ramalingam <ganesanr@netlogicmicro.com>

Add support for the intergrated I2C controller on Netlogic
XLR/XLS MIPS SoC.

The changes are to add a new file i2c/buses/i2c-xlr.c, containing the
i2c bus implementation, and to update i2c/buses/{Kconfig,Makefile} to
add the CONFIG_I2C_XLR option.

Signed-off-by: Ganesan Ramalingam <ganesanr@netlogicmicro.com>
Signed-off-by: Jayachandran C <jayachandranc@netlogicmicro.com>
---

Changes from the last version is to remove the custom IO functions from
netlogic headers and use __raw_readl/__raw_writel

This has been sent out too many times now, please let me know if there 
are any comments.

 drivers/i2c/busses/Kconfig   |   11 ++
 drivers/i2c/busses/Makefile  |    1 +
 drivers/i2c/busses/i2c-xlr.c |  318 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 330 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-xlr.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a3afac4..c9f3db3 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -308,6 +308,17 @@ config I2C_AU1550
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-au1550.
 
+config I2C_XLR
+	tristate "XLR I2C support"
+	depends on CPU_XLR
+	help
+	  This driver enables support for the on-chip I2C interface of
+	  the Netlogic XLR/XLS MIPS processors.
+
+	  Say yes to this option if you have a Netlogic XLR/XLS based
+	  board and you need to access the I2C devices (typically the
+	  RTC, sensors, EEPROM) connected to this interface.
+
 config I2C_BLACKFIN_TWI
 	tristate "Blackfin TWI I2C support"
 	depends on BLACKFIN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index fba6da6..4372dee 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
+obj-$(CONFIG_I2C_XLR)           += i2c-xlr.o
 obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
 
 # External I2C/SMBus adapter drivers
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
new file mode 100644
index 0000000..cc2f0a5
--- /dev/null
+++ b/drivers/i2c/busses/i2c-xlr.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2011, Netlogic Microsystems Inc.
+ * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+/* XLR I2C REGISTERS */
+#define XLR_I2C_CFG		0x00
+#define XLR_I2C_CLKDIV		0x01
+#define XLR_I2C_DEVADDR		0x02
+#define XLR_I2C_ADDR		0x03
+#define XLR_I2C_DATAOUT		0x04
+#define XLR_I2C_DATAIN		0x05
+#define XLR_I2C_STATUS		0x06
+#define XLR_I2C_STARTXFR	0x07
+#define XLR_I2C_BYTECNT		0x08
+#define XLR_I2C_HDSTATIM	0x09
+
+/* XLR I2C REGISTERS FLAGS */
+#define XLR_I2C_BUS_BUSY	0x01
+#define XLR_I2C_SDOEMPTY	0x02
+#define XLR_I2C_RXRDY		0x04
+#define XLR_I2C_ACK_ERR		0x08
+#define XLR_I2C_ARB_STARTERR	0x30
+
+/* Register Programming Values!! Change as required */
+#define XLR_I2C_CFG_ADDR	0xF8    /* 8-Bit dev Addr + POR Values */
+#define XLR_I2C_CFG_NOADDR	0xFA    /* 8-Bit reg Addr + POR Values */
+#define XLR_I2C_STARTXFR_ND	0x02    /* No data , only addr */
+#define XLR_I2C_STARTXFR_RD	0x01    /* Read */
+#define XLR_I2C_STARTXFR_WR	0x00    /* Write */
+#define XLR_I2C_CLKDIV_DEF	0x14A   /* 0x00000052 */
+#define XLR_I2C_HDSTATIM_DEF	0x107   /* 0x00000000 */
+
+#define XLR_I2C_IO_SIZE		0x1000
+
+
+/* 
+ * Need un-swapped IO for the SoC I2C registers, use __raw_ IO
+ */
+static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
+{
+	base += reg;
+	__raw_writel(val, base);
+}
+
+static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
+{
+	base += reg;
+	return __raw_readl(base);
+}
+
+struct xlr_i2c_private {
+	struct i2c_adapter adap;
+	u32 __iomem *iobase;
+};
+
+static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
+		u8 *buf, u16 addr)
+{
+	u32 i2c_status = 0x00;
+	u8 nb;
+	int pos, timeout = 0;
+	struct i2c_adapter *adap = &priv->adap;
+	u8 offset = buf[0];
+
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len-1);
+
+retry:
+	timeout = 0;
+	pos = 1;
+	if (len == 1) {
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+				XLR_I2C_STARTXFR_ND);
+	} else {
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+				XLR_I2C_STARTXFR_WR);
+	}
+
+	while (1) {
+		if (timeout++ > 0x1000) {
+			dev_err(&adap->dev, "XLR_I2C_STARTXFR_RD Rx Timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		i2c_status = xlr_i2c_rdreg(priv->iobase,
+				XLR_I2C_STATUS);
+
+		if (i2c_status & XLR_I2C_SDOEMPTY) {
+			pos++;
+			nb = (pos < len) ? buf[pos] : 0;
+			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, nb);
+		}
+
+		if (i2c_status & XLR_I2C_ARB_STARTERR)
+			goto retry;
+
+		if (i2c_status & XLR_I2C_ACK_ERR) {
+			return -EIO;
+		}
+
+		if (i2c_status & XLR_I2C_BUS_BUSY) {
+			udelay(1);
+			continue;
+		}
+
+		if (pos >= len)
+			break;
+	}
+
+	return 0;
+}
+
+static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len,
+		u8 *buf, u16 addr)
+{
+	u32 i2c_status = 0x00;
+	int pos = 0;
+	int timeout = 0;
+	struct i2c_adapter *adap = &priv->adap;
+
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+
+retry:
+	timeout = 0;
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+			XLR_I2C_STARTXFR_RD);
+
+	while (1) {
+		if (timeout++ > 0x1000) {
+			dev_err(&adap->dev, "XLR_I2C_STARTXFR_RD Rx Timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		i2c_status = xlr_i2c_rdreg(priv->iobase,
+				XLR_I2C_STATUS);
+		if (i2c_status & XLR_I2C_RXRDY) {
+			buf[pos++] = (u8)xlr_i2c_rdreg(priv->iobase,
+					XLR_I2C_DATAIN);
+		}
+
+		if (i2c_status & XLR_I2C_ARB_STARTERR)
+			goto retry;
+
+		if (i2c_status & XLR_I2C_ACK_ERR) {
+			dev_err(&adap->dev, "XLR_I2C_STARTXFR_RD ACK ERR\n");
+			return -EIO;
+		}
+
+		if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
+			break;
+		udelay(1);
+	}
+	return 0;
+}
+
+static int xlr_i2c_xfer(struct i2c_adapter *adap,
+		struct i2c_msg *msgs, int num)
+{
+	struct i2c_msg *msg;
+	int i;
+	int ret = 0;
+	struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
+
+	for (i = 0; ret == 0 && i < num; i++) {
+		msg = &msgs[i];
+		if (msg->flags & I2C_M_RD)
+			ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
+					msg->addr);
+		else
+			ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
+					msg->addr);
+	}
+
+	return (ret != 0) ? ret : num;
+}
+
+static u32 xlr_func(struct i2c_adapter *adap)
+{
+	/* Emulate SMBUS over I2C */
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm xlr_i2c_algo = {
+	.master_xfer	= xlr_i2c_xfer,
+	.functionality	= xlr_func,
+};
+
+static int xlr_i2c_add_bus(struct xlr_i2c_private *priv)
+{
+	priv->adap.owner	= THIS_MODULE;
+	priv->adap.algo_data	= priv;
+	priv->adap.nr		= 1;
+	priv->adap.algo		= &xlr_i2c_algo;
+	priv->adap.class	= I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	snprintf(priv->adap.name, sizeof(priv->adap.name),
+			"SMBus XLR I2C Adapter");
+	i2c_set_adapdata(&priv->adap, priv);
+	/* register new adapter to i2c module... */
+	if (i2c_add_numbered_adapter(&priv->adap))
+		return -1;
+
+	return 0;
+}
+
+static int __devinit xlr_i2c_probe(struct platform_device *pdev)
+{
+	struct xlr_i2c_private  *priv;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!res) {
+		ret = -ENXIO;
+		goto err1;
+	}
+
+	if (!request_mem_region(res->start, XLR_I2C_IO_SIZE, pdev->name)) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	priv = kzalloc(sizeof(struct xlr_i2c_private), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	priv->adap.dev.parent = &pdev->dev;
+	priv->iobase = (u32 *)ioremap(res->start, XLR_I2C_IO_SIZE);
+	if (!priv->iobase) {
+		ret = -ENOMEM;
+		goto err3;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	ret = xlr_i2c_add_bus(priv);
+
+	if (ret < 0) {
+		dev_err(&priv->adap.dev, "Failed to add i2c bus\n");
+		ret = -ENXIO;
+		goto err4;
+	} else
+		dev_info(&priv->adap.dev, "Added I2C Bus.\n");
+
+	return 0;
+err4:
+	iounmap(priv->iobase);
+	platform_set_drvdata(pdev, NULL);
+err3:
+	kfree(priv);
+err2:
+	release_mem_region(res->start, IORESOURCE_MEM);
+err1:
+	return ret;
+}
+
+static int __devexit xlr_i2c_remove(struct platform_device *pdev)
+{
+	struct xlr_i2c_private *priv = platform_get_drvdata(pdev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	i2c_del_adapter(&priv->adap);
+	iounmap(priv->iobase);
+	kfree(priv);
+	release_mem_region(res->start, IORESOURCE_MEM);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver xlr_i2c_driver = {
+	.probe  = xlr_i2c_probe,
+	.remove = __devexit_p(xlr_i2c_remove),
+	.driver = {
+		.owner  = THIS_MODULE,
+		.name   = "xlr-i2cbus",
+	},
+};
+
+static int __init xlr_i2c_init(void)
+{
+	return platform_driver_register(&xlr_i2c_driver);
+}
+
+static void __exit xlr_i2c_exit(void)
+{
+	platform_driver_unregister(&xlr_i2c_driver);
+}
+
+MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@netlogicmicro.com>");
+MODULE_DESCRIPTION("XLR I2C SMBus driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:xlr-i2cbus");
+
+module_init(xlr_i2c_init);
+module_exit(xlr_i2c_exit);
-- 
1.7.5.4

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

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
  2011-11-15 17:54 Jayachandran C.
@ 2011-11-16 11:12 ` Shubhrajyoti Datta
  0 siblings, 0 replies; 17+ messages in thread
From: Shubhrajyoti Datta @ 2011-11-16 11:12 UTC (permalink / raw)
  To: Jayachandran C.; +Cc: linux-i2c, ben-linux, linux-mips, Ganesan Ramalingam

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

Hi Ganeshan,
Some minor comments.

On Tue, Nov 15, 2011 at 11:24 PM, Jayachandran C. <
jayachandranc@netlogicmicro.com> wrote:

> From: Ganesan Ramalingam <ganesanr@netlogicmicro.com>
>
> Add support for the intergrated I2C controller on Netlogic
> XLR/XLS MIPS SoC.
>
> The changes are to add a new file i2c/buses/i2c-xlr.c, containing the
> i2c bus implementation, and to update i2c/buses/{Kconfig,Makefile} to
> add the CONFIG_I2C_XLR option.
>
> Signed-off-by: Ganesan Ramalingam <ganesanr@netlogicmicro.com>
> Signed-off-by: Jayachandran C <jayachandranc@netlogicmicro.com>
> ---
>
> Changes from the last version is to remove the custom IO functions from
> netlogic headers and use __raw_readl/__raw_writel
>
> This has been sent out too many times now, please let me know if there
> are any comments.
>
>  drivers/i2c/busses/Kconfig   |   11 ++
>  drivers/i2c/busses/Makefile  |    1 +
>  drivers/i2c/busses/i2c-xlr.c |  318
> ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 330 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/busses/i2c-xlr.c
>
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index a3afac4..c9f3db3 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -308,6 +308,17 @@ config I2C_AU1550
>          This driver can also be built as a module.  If so, the module
>          will be called i2c-au1550.
>
> +config I2C_XLR
> +       tristate "XLR I2C support"
> +       depends on CPU_XLR
> +       help
> +         This driver enables support for the on-chip I2C interface of
> +         the Netlogic XLR/XLS MIPS processors.
> +
> +         Say yes to this option if you have a Netlogic XLR/XLS based
> +         board and you need to access the I2C devices (typically the
> +         RTC, sensors, EEPROM) connected to this interface.
>

You already have tristate how about the module support

> +
>  config I2C_BLACKFIN_TWI
>        tristate "Blackfin TWI I2C support"
>        depends on BLACKFIN
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index fba6da6..4372dee 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)               += i2c-tegra.o
>  obj-$(CONFIG_I2C_VERSATILE)    += i2c-versatile.o
>  obj-$(CONFIG_I2C_OCTEON)       += i2c-octeon.o
>  obj-$(CONFIG_I2C_XILINX)       += i2c-xiic.o
> +obj-$(CONFIG_I2C_XLR)           += i2c-xlr.o
>  obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
>
>  # External I2C/SMBus adapter drivers
> diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
> new file mode 100644
> index 0000000..cc2f0a5
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-xlr.c
> @@ -0,0 +1,318 @@
> +/*
> + * Copyright 2011, Netlogic Microsystems Inc.
> + * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/init.h>
> +#include <linux/ioport.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +
> +/* XLR I2C REGISTERS */
> +#define XLR_I2C_CFG            0x00
> +#define XLR_I2C_CLKDIV         0x01
> +#define XLR_I2C_DEVADDR                0x02
> +#define XLR_I2C_ADDR           0x03
> +#define XLR_I2C_DATAOUT                0x04
> +#define XLR_I2C_DATAIN         0x05
> +#define XLR_I2C_STATUS         0x06
> +#define XLR_I2C_STARTXFR       0x07
> +#define XLR_I2C_BYTECNT                0x08
> +#define XLR_I2C_HDSTATIM       0x09
> +
> +/* XLR I2C REGISTERS FLAGS */
> +#define XLR_I2C_BUS_BUSY       0x01
> +#define XLR_I2C_SDOEMPTY       0x02
> +#define XLR_I2C_RXRDY          0x04
> +#define XLR_I2C_ACK_ERR                0x08
> +#define XLR_I2C_ARB_STARTERR   0x30
> +
> +/* Register Programming Values!! Change as required */
> +#define XLR_I2C_CFG_ADDR       0xF8    /* 8-Bit dev Addr + POR Values */
> +#define XLR_I2C_CFG_NOADDR     0xFA    /* 8-Bit reg Addr + POR Values */
> +#define XLR_I2C_STARTXFR_ND    0x02    /* No data , only addr */
> +#define XLR_I2C_STARTXFR_RD    0x01    /* Read */
> +#define XLR_I2C_STARTXFR_WR    0x00    /* Write */
> +#define XLR_I2C_CLKDIV_DEF     0x14A   /* 0x00000052 */
> +#define XLR_I2C_HDSTATIM_DEF   0x107   /* 0x00000000 */
> +
> +#define XLR_I2C_IO_SIZE                0x1000
> +
> +
> +/*
> + * Need un-swapped IO for the SoC I2C registers, use __raw_ IO
> + */
> +static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32
> val)
> +{
> +       base += reg;
> +       __raw_writel(val, base);
> +}
> +
> +static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
> +{
> +       base += reg;
> +       return __raw_readl(base);
> +}
> +
> +struct xlr_i2c_private {
> +       struct i2c_adapter adap;
> +       u32 __iomem *iobase;
> +};
> +
> +static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
> +               u8 *buf, u16 addr)
> +{
> +       u32 i2c_status = 0x00;
> +       u8 nb;
> +       int pos, timeout = 0;
> +       struct i2c_adapter *adap = &priv->adap;
> +       u8 offset = buf[0];
> +
> +       xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
> +       xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +       xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
> +       xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len-1);
> +
> +retry:
> +       timeout = 0;
> +       pos = 1;
> +       if (len == 1) {
> +               xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +                               XLR_I2C_STARTXFR_ND);
> +       } else {
> +               xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
> +               xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +                               XLR_I2C_STARTXFR_WR);
> +       }
> +
> +       while (1) {
> +               if (timeout++ > 0x1000) {
>

Could this be a macro?



> +                       dev_err(&adap->dev, "XLR_I2C_STARTXFR_RD Rx
> Timeout\n");
> +                       return -ETIMEDOUT;
> +               }
> +
> +               i2c_status = xlr_i2c_rdreg(priv->iobase,
> +                               XLR_I2C_STATUS);
> +
> +               if (i2c_status & XLR_I2C_SDOEMPTY) {
> +                       pos++;
> +                       nb = (pos < len) ? buf[pos] : 0;
> +                       xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, nb);
> +               }
> +
> +               if (i2c_status & XLR_I2C_ARB_STARTERR)
> +                       goto retry;
> +
> +               if (i2c_status & XLR_I2C_ACK_ERR) {
> +                       return -EIO;
> +               }
> +
> +               if (i2c_status & XLR_I2C_BUS_BUSY) {
> +                       udelay(1);
> +                       continue;
> +               }
> +
> +               if (pos >= len)
> +                       break;
> +       }
> +
> +       return 0;
> +}
> +
> +static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len,
> +               u8 *buf, u16 addr)
> +{
> +       u32 i2c_status = 0x00;
> +       int pos = 0;
> +       int timeout = 0;
> +       struct i2c_adapter *adap = &priv->adap;
> +
> +       xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
> +       xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
> +       xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +
> +retry:
> +       timeout = 0;
> +       xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +                       XLR_I2C_STARTXFR_RD);
> +
> +       while (1) {
> +               if (timeout++ > 0x1000) {
> +                       dev_err(&adap->dev, "XLR_I2C_STARTXFR_RD Rx
> Timeout\n");
> +                       return -ETIMEDOUT;
> +               }
> +
> +               i2c_status = xlr_i2c_rdreg(priv->iobase,
> +                               XLR_I2C_STATUS);
> +               if (i2c_status & XLR_I2C_RXRDY) {
> +                       buf[pos++] = (u8)xlr_i2c_rdreg(priv->iobase,
> +                                       XLR_I2C_DATAIN);
> +               }
> +
> +               if (i2c_status & XLR_I2C_ARB_STARTERR)
> +                       goto retry;
> +
> +               if (i2c_status & XLR_I2C_ACK_ERR) {
> +                       dev_err(&adap->dev, "XLR_I2C_STARTXFR_RD ACK
> ERR\n");
> +                       return -EIO;
> +               }
> +
> +               if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
> +                       break;
> +               udelay(1);
> +       }
> +       return 0;
> +}
> +
> +static int xlr_i2c_xfer(struct i2c_adapter *adap,
> +               struct i2c_msg *msgs, int num)
> +{
> +       struct i2c_msg *msg;
> +       int i;
> +       int ret = 0;
> +       struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
> +
> +       for (i = 0; ret == 0 && i < num; i++) {
> +               msg = &msgs[i];
> +               if (msg->flags & I2C_M_RD)
> +                       ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
> +                                       msg->addr);
> +               else
> +                       ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
> +                                       msg->addr);
> +       }
> +
> +       return (ret != 0) ? ret : num;
> +}
> +
> +static u32 xlr_func(struct i2c_adapter *adap)
> +{
> +       /* Emulate SMBUS over I2C */
> +       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
> +}
> +
> +static struct i2c_algorithm xlr_i2c_algo = {
> +       .master_xfer    = xlr_i2c_xfer,
> +       .functionality  = xlr_func,
> +};
> +
> +static int xlr_i2c_add_bus(struct xlr_i2c_private *priv)
> +{
> +       priv->adap.owner        = THIS_MODULE;
> +       priv->adap.algo_data    = priv;
> +       priv->adap.nr           = 1;
> +       priv->adap.algo         = &xlr_i2c_algo;
> +       priv->adap.class        = I2C_CLASS_HWMON | I2C_CLASS_SPD;
> +       snprintf(priv->adap.name, sizeof(priv->adap.name),
> +                       "SMBus XLR I2C Adapter");
> +       i2c_set_adapdata(&priv->adap, priv);
> +       /* register new adapter to i2c module... */
> +       if (i2c_add_numbered_adapter(&priv->adap))
> +               return -1;
> +
> +       return 0;
> +}
> +
> +static int __devinit xlr_i2c_probe(struct platform_device *pdev)
> +{
> +       struct xlr_i2c_private  *priv;
> +       struct resource *res;
> +       int ret;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +       if (!res) {
> +               ret = -ENXIO;
> +               goto err1;
> +       }
> +
> +       if (!request_mem_region(res->start, XLR_I2C_IO_SIZE, pdev->name)) {
> +               dev_err(&pdev->dev, "request_mem_region failed\n");
> +               ret = -ENOMEM;
> +               goto err1;
>
The names could be more meaningful like err_req_mem or err_get_res etc.

> +       }
> +
> +       priv = kzalloc(sizeof(struct xlr_i2c_private), GFP_KERNEL);
> +       if (!priv) {
> +               ret = -ENOMEM;
> +               goto err2;
> +       }
> +
> +       priv->adap.dev.parent = &pdev->dev;
> +       priv->iobase = (u32 *)ioremap(res->start, XLR_I2C_IO_SIZE);
> +       if (!priv->iobase) {
> +               ret = -ENOMEM;
> +               goto err3;
> +       }
> +
> +       platform_set_drvdata(pdev, priv);
> +       ret = xlr_i2c_add_bus(priv);
> +
> +       if (ret < 0) {
> +               dev_err(&priv->adap.dev, "Failed to add i2c bus\n");
> +               ret = -ENXIO;
> +               goto err4;
> +       } else
> +               dev_info(&priv->adap.dev, "Added I2C Bus.\n");
> +
> +       return 0;
> +err4:
> +       iounmap(priv->iobase);
> +       platform_set_drvdata(pdev, NULL);
> +err3:
> +       kfree(priv);
> +err2:
> +       release_mem_region(res->start, IORESOURCE_MEM);
> +err1:
> +       return ret;
> +}
> +
> +static int __devexit xlr_i2c_remove(struct platform_device *pdev)
> +{
> +       struct xlr_i2c_private *priv = platform_get_drvdata(pdev);
> +       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM,
> 0);
> +
> +       i2c_del_adapter(&priv->adap);
> +       iounmap(priv->iobase);
> +       kfree(priv);
> +       release_mem_region(res->start, IORESOURCE_MEM);
> +       platform_set_drvdata(pdev, NULL);
> +       return 0;
> +}
> +
> +static struct platform_driver xlr_i2c_driver = {
> +       .probe  = xlr_i2c_probe,
> +       .remove = __devexit_p(xlr_i2c_remove),
> +       .driver = {
> +               .owner  = THIS_MODULE,
> +               .name   = "xlr-i2cbus",
> +       },
> +};
> +
> +static int __init xlr_i2c_init(void)
> +{
> +       return platform_driver_register(&xlr_i2c_driver);
> +}
> +
> +static void __exit xlr_i2c_exit(void)
> +{
> +       platform_driver_unregister(&xlr_i2c_driver);
> +}
> +
> +MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@netlogicmicro.com>");
> +MODULE_DESCRIPTION("XLR I2C SMBus driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:xlr-i2cbus");
> +
> +module_init(xlr_i2c_init);
> +module_exit(xlr_i2c_exit);
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

[-- Attachment #2: Type: text/html, Size: 16385 bytes --]

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

* [PATCH] Support for Netlogic XLR/XLS I2C controller
@ 2012-01-17 13:48 Jayachandran C.
       [not found] ` <1326808100-22540-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Jayachandran C. @ 2012-01-17 13:48 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: khali-PUYAD+kWke1g9hUCZPvPmw, inux-mips-6z/3iImG2C8G8FEW9MqTrA,
	Jayachandran C

From: Jayachandran C <jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>

This patch adds support to the I2C controller on Netlogic XLR/XLS
multi-core MIPS SoCs.

The patch has been sent out a many times already, and all the comments
we have seen are already taken care of.

It is a polling driver, but that is not an issue in our current usage
(and we have many CPUs on-chip).

Ganesan Ramalingam (1):
  i2c: Support for Netlogic XLR/XLS I2C controller.

 drivers/i2c/busses/Kconfig   |   14 ++
 drivers/i2c/busses/Makefile  |    1 +
 drivers/i2c/busses/i2c-xlr.c |  307 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 322 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-xlr.c

-- 
1.7.5.4

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

* [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found] ` <1326808100-22540-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
@ 2012-01-17 13:48   ` Jayachandran C.
       [not found]     ` <1326808100-22540-2-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Jayachandran C. @ 2012-01-17 13:48 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: khali-PUYAD+kWke1g9hUCZPvPmw, inux-mips-6z/3iImG2C8G8FEW9MqTrA,
	Ganesan Ramalingam, Jayachandran C

From: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>

Add support for the intergrated I2C controller on Netlogic
XLR/XLS MIPS SoC.

The changes are to add a new file i2c/buses/i2c-xlr.c, containing the
i2c bus implementation, and to update i2c/buses/{Kconfig,Makefile} to
add the CONFIG_I2C_XLR option.

Signed-off-by: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
Signed-off-by: Jayachandran C <jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
---
 drivers/i2c/busses/Kconfig   |   14 ++
 drivers/i2c/busses/Makefile  |    1 +
 drivers/i2c/busses/i2c-xlr.c |  307 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 322 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-xlr.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index cbe7a2f..7052628 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -308,6 +308,20 @@ config I2C_AU1550
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-au1550.
 
+config I2C_XLR
+	tristate "XLR I2C support"
+	depends on CPU_XLR
+	help
+	  This driver enables support for the on-chip I2C interface of
+	  the Netlogic XLR/XLS MIPS processors.
+
+	  Say yes to this option if you have a Netlogic XLR/XLS based
+	  board and you need to access the I2C devices (typically the
+	  RTC, sensors, EEPROM) connected to this interface.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-au1550.
+
 config I2C_BLACKFIN_TWI
 	tristate "Blackfin TWI I2C support"
 	depends on BLACKFIN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index fba6da6..4372dee 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
+obj-$(CONFIG_I2C_XLR)           += i2c-xlr.o
 obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
 
 # External I2C/SMBus adapter drivers
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
new file mode 100644
index 0000000..6da0fa9
--- /dev/null
+++ b/drivers/i2c/busses/i2c-xlr.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2011, Netlogic Microsystems Inc.
+ * Copyright 2004, Matt Porter <mporter-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+/* XLR I2C REGISTERS */
+#define XLR_I2C_CFG		0x00
+#define XLR_I2C_CLKDIV		0x01
+#define XLR_I2C_DEVADDR		0x02
+#define XLR_I2C_ADDR		0x03
+#define XLR_I2C_DATAOUT		0x04
+#define XLR_I2C_DATAIN		0x05
+#define XLR_I2C_STATUS		0x06
+#define XLR_I2C_STARTXFR	0x07
+#define XLR_I2C_BYTECNT		0x08
+#define XLR_I2C_HDSTATIM	0x09
+
+/* XLR I2C REGISTERS FLAGS */
+#define XLR_I2C_BUS_BUSY	0x01
+#define XLR_I2C_SDOEMPTY	0x02
+#define XLR_I2C_RXRDY		0x04
+#define XLR_I2C_ACK_ERR		0x08
+#define XLR_I2C_ARB_STARTERR	0x30
+
+/* Register Values */
+#define XLR_I2C_CFG_ADDR	0xF8
+#define XLR_I2C_CFG_NOADDR	0xFA
+#define XLR_I2C_STARTXFR_ND	0x02    /* No Data */
+#define XLR_I2C_STARTXFR_RD	0x01    /* Read */
+#define XLR_I2C_STARTXFR_WR	0x00    /* Write */
+
+#define XLR_I2C_IO_SIZE		0x1000
+
+#define MAX_RETRIES		10000 /* max retries per byte */
+/*
+ * Need un-swapped IO for the SoC I2C registers, use __raw_ IO
+ */
+static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
+{
+	__raw_writel(val, base + reg);
+}
+
+static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
+{
+	return __raw_readl(base + reg);
+}
+
+struct xlr_i2c_private {
+	struct i2c_adapter adap;
+	u32 __iomem *iobase;
+};
+
+static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
+		u8 *buf, u16 addr)
+{
+	struct i2c_adapter *adap = &priv->adap;
+	u32 i2c_status;
+	int pos, retries;
+	u8 offset, nb;
+
+	offset = buf[0];
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
+
+	retries = 0;
+retry:
+	pos = 1;
+	if (len == 1) {
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+				XLR_I2C_STARTXFR_ND);
+	} else {
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+				XLR_I2C_STARTXFR_WR);
+	}
+
+	while (1) {
+		if (retries++ > MAX_RETRIES) {
+			dev_err(&adap->dev, "I2C transmit timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
+
+		if (i2c_status & XLR_I2C_SDOEMPTY) {
+			pos++;
+			retries = 0;
+			nb = (pos < len) ? buf[pos] : 0;
+			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, nb);
+		}
+
+		if (i2c_status & XLR_I2C_ARB_STARTERR)
+			goto retry;
+
+		if (i2c_status & XLR_I2C_ACK_ERR)
+			return -EIO;
+
+		if (i2c_status & XLR_I2C_BUS_BUSY)
+			continue;
+
+		if (pos >= len)
+			break;
+	}
+
+	return 0;
+}
+
+static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
+{
+	struct i2c_adapter *adap = &priv->adap;
+	u32 i2c_status;
+	int pos, retries;
+
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+
+	retries = 0;
+	pos = 0;
+retry:
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
+
+	while (1) {
+		if (retries++ > MAX_RETRIES) {
+			dev_err(&adap->dev, "I2C receive timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
+		if (i2c_status & XLR_I2C_RXRDY) {
+			buf[pos++] = (u8)xlr_i2c_rdreg(priv->iobase,
+					XLR_I2C_DATAIN);
+			retries = 0;
+		}
+
+		if (i2c_status & XLR_I2C_ARB_STARTERR)
+			goto retry;
+
+		if (i2c_status & XLR_I2C_ACK_ERR) {
+			dev_err(&adap->dev, "I2C receive ACK error\n");
+			return -EIO;
+		}
+
+		if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
+			break;
+	}
+	return 0;
+}
+
+static int xlr_i2c_xfer(struct i2c_adapter *adap,
+		struct i2c_msg *msgs, int num)
+{
+	struct i2c_msg *msg;
+	int i;
+	int ret = 0;
+	struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
+
+	for (i = 0; ret == 0 && i < num; i++) {
+		msg = &msgs[i];
+		if (msg->flags & I2C_M_RD)
+			ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
+					msg->addr);
+		else
+			ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
+					msg->addr);
+	}
+
+	return (ret != 0) ? ret : num;
+}
+
+static u32 xlr_func(struct i2c_adapter *adap)
+{
+	/* Emulate SMBUS over I2C */
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm xlr_i2c_algo = {
+	.master_xfer	= xlr_i2c_xfer,
+	.functionality	= xlr_func,
+};
+
+static int xlr_i2c_add_bus(struct xlr_i2c_private *priv)
+{
+	priv->adap.owner	= THIS_MODULE;
+	priv->adap.algo_data	= priv;
+	priv->adap.nr		= 1;
+	priv->adap.algo		= &xlr_i2c_algo;
+	priv->adap.class	= I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	snprintf(priv->adap.name, sizeof(priv->adap.name),
+			"SMBus XLR I2C Adapter");
+	i2c_set_adapdata(&priv->adap, priv);
+	/* register new adapter to i2c module... */
+	if (i2c_add_numbered_adapter(&priv->adap))
+		return -1;
+
+	return 0;
+}
+
+static int __devinit xlr_i2c_probe(struct platform_device *pdev)
+{
+	struct xlr_i2c_private  *priv;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!res) {
+		ret = -ENXIO;
+		goto err1;
+	}
+
+	if (!request_mem_region(res->start, XLR_I2C_IO_SIZE, pdev->name)) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	priv->adap.dev.parent = &pdev->dev;
+	priv->iobase = ioremap(res->start, XLR_I2C_IO_SIZE);
+	if (!priv->iobase) {
+		ret = -ENOMEM;
+		goto err3;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	ret = xlr_i2c_add_bus(priv);
+
+	if (ret < 0) {
+		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
+		ret = -ENXIO;
+		goto err4;
+	} else
+		dev_info(&priv->adap.dev, "Added I2C Bus.\n");
+
+	return 0;
+err4:
+	iounmap(priv->iobase);
+	platform_set_drvdata(pdev, NULL);
+err3:
+	kfree(priv);
+err2:
+	release_mem_region(res->start, IORESOURCE_MEM);
+err1:
+	return ret;
+}
+
+static int __devexit xlr_i2c_remove(struct platform_device *pdev)
+{
+	struct xlr_i2c_private *priv = platform_get_drvdata(pdev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	i2c_del_adapter(&priv->adap);
+	iounmap(priv->iobase);
+	kfree(priv);
+	release_mem_region(res->start, IORESOURCE_MEM);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver xlr_i2c_driver = {
+	.probe  = xlr_i2c_probe,
+	.remove = __devexit_p(xlr_i2c_remove),
+	.driver = {
+		.owner  = THIS_MODULE,
+		.name   = "xlr-i2cbus",
+	},
+};
+
+static int __init xlr_i2c_init(void)
+{
+	return platform_driver_register(&xlr_i2c_driver);
+}
+
+static void __exit xlr_i2c_exit(void)
+{
+	platform_driver_unregister(&xlr_i2c_driver);
+}
+
+MODULE_AUTHOR("Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>");
+MODULE_DESCRIPTION("XLR I2C SMBus driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:xlr-i2cbus");
+
+module_init(xlr_i2c_init);
+module_exit(xlr_i2c_exit);
-- 
1.7.5.4

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

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]     ` <1326808100-22540-2-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
@ 2012-01-17 23:23       ` Ben Dooks
       [not found]         ` <20120117232318.GB7774-RazCHl0VsYgkUSuvROHNpA@public.gmane.org>
  2012-01-18  9:10       ` Wolfram Sang
  1 sibling, 1 reply; 17+ messages in thread
From: Ben Dooks @ 2012-01-17 23:23 UTC (permalink / raw)
  To: Jayachandran C.
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ,
	khali-PUYAD+kWke1g9hUCZPvPmw, inux-mips-6z/3iImG2C8G8FEW9MqTrA,
	Ganesan Ramalingam

On Tue, Jan 17, 2012 at 07:18:20PM +0530, Jayachandran C. wrote:
> From: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
> 
> Add support for the intergrated I2C controller on Netlogic
> XLR/XLS MIPS SoC.
> 
> The changes are to add a new file i2c/buses/i2c-xlr.c, containing the
> i2c bus implementation, and to update i2c/buses/{Kconfig,Makefile} to
> add the CONFIG_I2C_XLR option.
> 
> Signed-off-by: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
> Signed-off-by: Jayachandran C <jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
> ---
>  drivers/i2c/busses/Kconfig   |   14 ++
>  drivers/i2c/busses/Makefile  |    1 +
>  drivers/i2c/busses/i2c-xlr.c |  307 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 322 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/busses/i2c-xlr.c
> 
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index cbe7a2f..7052628 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -308,6 +308,20 @@ config I2C_AU1550
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called i2c-au1550.
>  
> +config I2C_XLR
> +	tristate "XLR I2C support"
> +	depends on CPU_XLR
> +	help
> +	  This driver enables support for the on-chip I2C interface of
> +	  the Netlogic XLR/XLS MIPS processors.
> +
> +	  Say yes to this option if you have a Netlogic XLR/XLS based
> +	  board and you need to access the I2C devices (typically the
> +	  RTC, sensors, EEPROM) connected to this interface.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-au1550.
> +
>  config I2C_BLACKFIN_TWI
>  	tristate "Blackfin TWI I2C support"
>  	depends on BLACKFIN
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index fba6da6..4372dee 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
>  obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
>  obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
>  obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
> +obj-$(CONFIG_I2C_XLR)           += i2c-xlr.o
>  obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
>  
>  # External I2C/SMBus adapter drivers
> diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
> new file mode 100644
> index 0000000..6da0fa9
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-xlr.c
> @@ -0,0 +1,307 @@
> +/*
> + * Copyright 2011, Netlogic Microsystems Inc.
> + * Copyright 2004, Matt Porter <mporter-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/init.h>
> +#include <linux/ioport.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +
> +/* XLR I2C REGISTERS */
> +#define XLR_I2C_CFG		0x00
> +#define XLR_I2C_CLKDIV		0x01
> +#define XLR_I2C_DEVADDR		0x02
> +#define XLR_I2C_ADDR		0x03
> +#define XLR_I2C_DATAOUT		0x04
> +#define XLR_I2C_DATAIN		0x05
> +#define XLR_I2C_STATUS		0x06
> +#define XLR_I2C_STARTXFR	0x07
> +#define XLR_I2C_BYTECNT		0x08
> +#define XLR_I2C_HDSTATIM	0x09
> +
> +/* XLR I2C REGISTERS FLAGS */
> +#define XLR_I2C_BUS_BUSY	0x01
> +#define XLR_I2C_SDOEMPTY	0x02
> +#define XLR_I2C_RXRDY		0x04
> +#define XLR_I2C_ACK_ERR		0x08
> +#define XLR_I2C_ARB_STARTERR	0x30
> +
> +/* Register Values */
> +#define XLR_I2C_CFG_ADDR	0xF8
> +#define XLR_I2C_CFG_NOADDR	0xFA
> +#define XLR_I2C_STARTXFR_ND	0x02    /* No Data */
> +#define XLR_I2C_STARTXFR_RD	0x01    /* Read */
> +#define XLR_I2C_STARTXFR_WR	0x00    /* Write */
> +
> +#define XLR_I2C_IO_SIZE		0x1000
> +
> +#define MAX_RETRIES		10000 /* max retries per byte */
> +/*
> + * Need un-swapped IO for the SoC I2C registers, use __raw_ IO
> + */
> +static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
> +{
> +	__raw_writel(val, base + reg);
> +}
> +
> +static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
> +{
> +	return __raw_readl(base + reg);
> +}

Here, there's the use of __raw accessors with memory returned from
ioremap(). Please use readl/writel here, or provide a _good_ reason
for not using them.

> +struct xlr_i2c_private {
> +	struct i2c_adapter adap;
> +	u32 __iomem *iobase;
> +};
> +
> +static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
> +		u8 *buf, u16 addr)
> +{
> +	struct i2c_adapter *adap = &priv->adap;
> +	u32 i2c_status;
> +	int pos, retries;
> +	u8 offset, nb;
> +
> +	offset = buf[0];
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
> +
> +	retries = 0;
> +retry:
> +	pos = 1;
> +	if (len == 1) {
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +				XLR_I2C_STARTXFR_ND);
> +	} else {
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +				XLR_I2C_STARTXFR_WR);
> +	}
> +
> +	while (1) {
> +		if (retries++ > MAX_RETRIES) {
> +			dev_err(&adap->dev, "I2C transmit timeout\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
> +
> +		if (i2c_status & XLR_I2C_SDOEMPTY) {
> +			pos++;
> +			retries = 0;
> +			nb = (pos < len) ? buf[pos] : 0;
> +			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, nb);
> +		}
> +
> +		if (i2c_status & XLR_I2C_ARB_STARTERR)
> +			goto retry;
> +
> +		if (i2c_status & XLR_I2C_ACK_ERR)
> +			return -EIO;
> +
> +		if (i2c_status & XLR_I2C_BUS_BUSY)
> +			continue;
> +
> +		if (pos >= len)
> +			break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
> +{
> +	struct i2c_adapter *adap = &priv->adap;
> +	u32 i2c_status;
> +	int pos, retries;
> +
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +
> +	retries = 0;
> +	pos = 0;
> +retry:
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
> +
> +	while (1) {
> +		if (retries++ > MAX_RETRIES) {
> +			dev_err(&adap->dev, "I2C receive timeout\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
> +		if (i2c_status & XLR_I2C_RXRDY) {
> +			buf[pos++] = (u8)xlr_i2c_rdreg(priv->iobase,
> +					XLR_I2C_DATAIN);
> +			retries = 0;
> +		}
> +
> +		if (i2c_status & XLR_I2C_ARB_STARTERR)
> +			goto retry;
> +
> +		if (i2c_status & XLR_I2C_ACK_ERR) {
> +			dev_err(&adap->dev, "I2C receive ACK error\n");
> +			return -EIO;
> +		}
> +
> +		if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
> +			break;
> +	}
> +	return 0;
> +}
> +
> +static int xlr_i2c_xfer(struct i2c_adapter *adap,
> +		struct i2c_msg *msgs, int num)
> +{
> +	struct i2c_msg *msg;
> +	int i;
> +	int ret = 0;
> +	struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
> +
> +	for (i = 0; ret == 0 && i < num; i++) {
> +		msg = &msgs[i];
> +		if (msg->flags & I2C_M_RD)
> +			ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
> +					msg->addr);
> +		else
> +			ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
> +					msg->addr);
> +	}
> +
> +	return (ret != 0) ? ret : num;
> +}
> +
> +static u32 xlr_func(struct i2c_adapter *adap)
> +{
> +	/* Emulate SMBUS over I2C */
> +	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
> +}
> +
> +static struct i2c_algorithm xlr_i2c_algo = {
> +	.master_xfer	= xlr_i2c_xfer,
> +	.functionality	= xlr_func,
> +};
> +
> +static int xlr_i2c_add_bus(struct xlr_i2c_private *priv)
> +{
> +	priv->adap.owner	= THIS_MODULE;
> +	priv->adap.algo_data	= priv;
> +	priv->adap.nr		= 1;
> +	priv->adap.algo		= &xlr_i2c_algo;
> +	priv->adap.class	= I2C_CLASS_HWMON | I2C_CLASS_SPD;
> +	snprintf(priv->adap.name, sizeof(priv->adap.name),
> +			"SMBus XLR I2C Adapter");
> +	i2c_set_adapdata(&priv->adap, priv);
> +	/* register new adapter to i2c module... */
> +	if (i2c_add_numbered_adapter(&priv->adap))
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static int __devinit xlr_i2c_probe(struct platform_device *pdev)
> +{
> +	struct xlr_i2c_private  *priv;
> +	struct resource *res;
> +	int ret;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	if (!res) {
> +		ret = -ENXIO;
> +		goto err1;
> +	}
> +
> +	if (!request_mem_region(res->start, XLR_I2C_IO_SIZE, pdev->name)) {
> +		dev_err(&pdev->dev, "request_mem_region failed\n");
> +		ret = -ENOMEM;
> +		goto err1;
> +	}
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		ret = -ENOMEM;
> +		goto err2;
> +	}
> +
> +	priv->adap.dev.parent = &pdev->dev;
> +	priv->iobase = ioremap(res->start, XLR_I2C_IO_SIZE);
> +	if (!priv->iobase) {
> +		ret = -ENOMEM;
> +		goto err3;
> +	}
> +
> +	platform_set_drvdata(pdev, priv);
> +	ret = xlr_i2c_add_bus(priv);
> +
> +	if (ret < 0) {
> +		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
> +		ret = -ENXIO;

Hmm, not sure if -ENXIO is the best return code form here. I would probably
leave the 'ret' alone, and pass it to the upper layer.

> +		goto err4;
> +	} else
> +		dev_info(&priv->adap.dev, "Added I2C Bus.\n");
> +
> +	return 0;
> +err4:
> +	iounmap(priv->iobase);
> +	platform_set_drvdata(pdev, NULL);
> +err3:
> +	kfree(priv);
> +err2:
> +	release_mem_region(res->start, IORESOURCE_MEM);
> +err1:
> +	return ret;
> +}
> +
> +static int __devexit xlr_i2c_remove(struct platform_device *pdev)
> +{
> +	struct xlr_i2c_private *priv = platform_get_drvdata(pdev);
> +	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	i2c_del_adapter(&priv->adap);
> +	iounmap(priv->iobase);
> +	kfree(priv);
> +	release_mem_region(res->start, IORESOURCE_MEM);
> +	platform_set_drvdata(pdev, NULL);
> +	return 0;
> +}
> +
> +static struct platform_driver xlr_i2c_driver = {
> +	.probe  = xlr_i2c_probe,
> +	.remove = __devexit_p(xlr_i2c_remove),
> +	.driver = {
> +		.owner  = THIS_MODULE,
> +		.name   = "xlr-i2cbus",
> +	},
> +};
> +
> +static int __init xlr_i2c_init(void)
> +{
> +	return platform_driver_register(&xlr_i2c_driver);
> +}
> +
> +static void __exit xlr_i2c_exit(void)
> +{
> +	platform_driver_unregister(&xlr_i2c_driver);
> +}
> +
> +MODULE_AUTHOR("Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>");
> +MODULE_DESCRIPTION("XLR I2C SMBus driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:xlr-i2cbus");
> +
> +module_init(xlr_i2c_init);
> +module_exit(xlr_i2c_exit);
> -- 
> 1.7.5.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]         ` <20120117232318.GB7774-RazCHl0VsYgkUSuvROHNpA@public.gmane.org>
@ 2012-01-18  6:28           ` Jayachandran C
  2012-01-18 15:33           ` [PATCH UPDATED] " Jayachandran C.
  1 sibling, 0 replies; 17+ messages in thread
From: Jayachandran C @ 2012-01-18  6:28 UTC (permalink / raw)
  To: Ben Dooks
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org,
	w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org,
	khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org, Ganesan R

Ben Dooks [ben-i2c-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org] wrote:
> On Tue, Jan 17, 2012 at 07:18:20PM +0530, Jayachandran C. wrote:
>> From: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
>>
>> Add support for the intergrated I2C controller on Netlogic
>> XLR/XLS MIPS SoC.
>>
>> +/*
>> + * Need un-swapped IO for the SoC I2C registers, use __raw_ IO
>> + */
>> +static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
>> +{
>> +     __raw_writel(val, base + reg);
>> +}
>> +
>> +static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
>> +{
>> +     return __raw_readl(base + reg);
>> +}
> 
> Here, there's the use of __raw accessors with memory returned from
> ioremap(). Please use readl/writel here, or provide a _good_ reason
> for not using them.

We had tried to explain it in the comment above the block.  The I2C registers on 
this SoC are in an MMIO area that is big-endian.  The PCI memory and IO space of
this SoC is  little-endian, and we have kept a byteswapping readl/writel so that the
generic PCI drivers will work.

>> +
>> +     platform_set_drvdata(pdev, priv);
>> +     ret = xlr_i2c_add_bus(priv);
>> +
>> +     if (ret < 0) {
>> +             dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
>> +             ret = -ENXIO;

> Hmm, not sure if -ENXIO is the best return code form here. I would probably
> leave the 'ret' alone, and pass it to the upper layer.

This can be fixed up.

Thanks for the review, will post an updated version.
JC.

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

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]     ` <1326808100-22540-2-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
  2012-01-17 23:23       ` Ben Dooks
@ 2012-01-18  9:10       ` Wolfram Sang
  1 sibling, 0 replies; 17+ messages in thread
From: Wolfram Sang @ 2012-01-18  9:10 UTC (permalink / raw)
  To: Jayachandran C.
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, khali-PUYAD+kWke1g9hUCZPvPmw,
	inux-mips-6z/3iImG2C8G8FEW9MqTrA, Ganesan Ramalingam

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

On Tue, Jan 17, 2012 at 07:18:20PM +0530, Jayachandran C. wrote:
> From: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
> 
> Add support for the intergrated I2C controller on Netlogic
> XLR/XLS MIPS SoC.
> 
> The changes are to add a new file i2c/buses/i2c-xlr.c, containing the
> i2c bus implementation, and to update i2c/buses/{Kconfig,Makefile} to
> add the CONFIG_I2C_XLR option.
> 
> Signed-off-by: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
> Signed-off-by: Jayachandran C <jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
> ---
>  drivers/i2c/busses/Kconfig   |   14 ++
>  drivers/i2c/busses/Makefile  |    1 +
>  drivers/i2c/busses/i2c-xlr.c |  307 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 322 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/busses/i2c-xlr.c
> 
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index cbe7a2f..7052628 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -308,6 +308,20 @@ config I2C_AU1550
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called i2c-au1550.
>  
> +config I2C_XLR
> +	tristate "XLR I2C support"
> +	depends on CPU_XLR
> +	help
> +	  This driver enables support for the on-chip I2C interface of
> +	  the Netlogic XLR/XLS MIPS processors.
> +
> +	  Say yes to this option if you have a Netlogic XLR/XLS based
> +	  board and you need to access the I2C devices (typically the
> +	  RTC, sensors, EEPROM) connected to this interface.
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-au1550.
> +

sorting broken

>  config I2C_BLACKFIN_TWI
>  	tristate "Blackfin TWI I2C support"
>  	depends on BLACKFIN
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index fba6da6..4372dee 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
>  obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
>  obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
>  obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
> +obj-$(CONFIG_I2C_XLR)           += i2c-xlr.o
>  obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
>  
>  # External I2C/SMBus adapter drivers
> diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
> new file mode 100644
> index 0000000..6da0fa9
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-xlr.c
> @@ -0,0 +1,307 @@
> +/*
> + * Copyright 2011, Netlogic Microsystems Inc.
> + * Copyright 2004, Matt Porter <mporter-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/init.h>
> +#include <linux/ioport.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +
> +/* XLR I2C REGISTERS */
> +#define XLR_I2C_CFG		0x00
> +#define XLR_I2C_CLKDIV		0x01
> +#define XLR_I2C_DEVADDR		0x02
> +#define XLR_I2C_ADDR		0x03
> +#define XLR_I2C_DATAOUT		0x04
> +#define XLR_I2C_DATAIN		0x05
> +#define XLR_I2C_STATUS		0x06
> +#define XLR_I2C_STARTXFR	0x07
> +#define XLR_I2C_BYTECNT		0x08
> +#define XLR_I2C_HDSTATIM	0x09
> +
> +/* XLR I2C REGISTERS FLAGS */
> +#define XLR_I2C_BUS_BUSY	0x01
> +#define XLR_I2C_SDOEMPTY	0x02
> +#define XLR_I2C_RXRDY		0x04
> +#define XLR_I2C_ACK_ERR		0x08
> +#define XLR_I2C_ARB_STARTERR	0x30
> +
> +/* Register Values */
> +#define XLR_I2C_CFG_ADDR	0xF8
> +#define XLR_I2C_CFG_NOADDR	0xFA
> +#define XLR_I2C_STARTXFR_ND	0x02    /* No Data */
> +#define XLR_I2C_STARTXFR_RD	0x01    /* Read */
> +#define XLR_I2C_STARTXFR_WR	0x00    /* Write */
> +
> +#define XLR_I2C_IO_SIZE		0x1000
> +
> +#define MAX_RETRIES		10000 /* max retries per byte */
> +/*
> + * Need un-swapped IO for the SoC I2C registers, use __raw_ IO
> + */
> +static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
> +{
> +	__raw_writel(val, base + reg);
> +}
> +
> +static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
> +{
> +	return __raw_readl(base + reg);
> +}
> +
> +struct xlr_i2c_private {
> +	struct i2c_adapter adap;
> +	u32 __iomem *iobase;
> +};
> +
> +static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
> +		u8 *buf, u16 addr)
> +{
> +	struct i2c_adapter *adap = &priv->adap;
> +	u32 i2c_status;
> +	int pos, retries;
> +	u8 offset, nb;
> +
> +	offset = buf[0];
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
> +
> +	retries = 0;
> +retry:
> +	pos = 1;
> +	if (len == 1) {
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +				XLR_I2C_STARTXFR_ND);
> +	} else {
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +				XLR_I2C_STARTXFR_WR);
> +	}
> +
> +	while (1) {
> +		if (retries++ > MAX_RETRIES) {
> +			dev_err(&adap->dev, "I2C transmit timeout\n");
> +			return -ETIMEDOUT;
> +		}

A timeout should be in us or ms, but not in loop counts.

> +
> +		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
> +
> +		if (i2c_status & XLR_I2C_SDOEMPTY) {
> +			pos++;
> +			retries = 0;
> +			nb = (pos < len) ? buf[pos] : 0;
> +			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, nb);
> +		}
> +
> +		if (i2c_status & XLR_I2C_ARB_STARTERR)
> +			goto retry;
> +
> +		if (i2c_status & XLR_I2C_ACK_ERR)
> +			return -EIO;
> +
> +		if (i2c_status & XLR_I2C_BUS_BUSY)
> +			continue;
> +
> +		if (pos >= len)
> +			break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
> +{
> +	struct i2c_adapter *adap = &priv->adap;
> +	u32 i2c_status;
> +	int pos, retries;
> +
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +
> +	retries = 0;
> +	pos = 0;
> +retry:
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
> +
> +	while (1) {
> +		if (retries++ > MAX_RETRIES) {
> +			dev_err(&adap->dev, "I2C receive timeout\n");
> +			return -ETIMEDOUT;
> +		}

ditto.

> +
> +		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
> +		if (i2c_status & XLR_I2C_RXRDY) {
> +			buf[pos++] = (u8)xlr_i2c_rdreg(priv->iobase,
> +					XLR_I2C_DATAIN);
> +			retries = 0;
> +		}
> +
> +		if (i2c_status & XLR_I2C_ARB_STARTERR)
> +			goto retry;
> +
> +		if (i2c_status & XLR_I2C_ACK_ERR) {
> +			dev_err(&adap->dev, "I2C receive ACK error\n");
> +			return -EIO;
> +		}
> +
> +		if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
> +			break;
> +	}
> +	return 0;
> +}
> +
> +static int xlr_i2c_xfer(struct i2c_adapter *adap,
> +		struct i2c_msg *msgs, int num)
> +{
> +	struct i2c_msg *msg;
> +	int i;
> +	int ret = 0;
> +	struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
> +
> +	for (i = 0; ret == 0 && i < num; i++) {
> +		msg = &msgs[i];
> +		if (msg->flags & I2C_M_RD)
> +			ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
> +					msg->addr);
> +		else
> +			ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
> +					msg->addr);
> +	}
> +
> +	return (ret != 0) ? ret : num;
> +}
> +
> +static u32 xlr_func(struct i2c_adapter *adap)
> +{
> +	/* Emulate SMBUS over I2C */
> +	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
> +}
> +
> +static struct i2c_algorithm xlr_i2c_algo = {
> +	.master_xfer	= xlr_i2c_xfer,
> +	.functionality	= xlr_func,
> +};
> +
> +static int xlr_i2c_add_bus(struct xlr_i2c_private *priv)
> +{
> +	priv->adap.owner	= THIS_MODULE;
> +	priv->adap.algo_data	= priv;
> +	priv->adap.nr		= 1;

Fixed number? And if somebody adds some extra external busses?

> +	priv->adap.algo		= &xlr_i2c_algo;
> +	priv->adap.class	= I2C_CLASS_HWMON | I2C_CLASS_SPD;

Are you sure you need the class?

> +	snprintf(priv->adap.name, sizeof(priv->adap.name),
> +			"SMBus XLR I2C Adapter");

really "SMBus"?

> +	i2c_set_adapdata(&priv->adap, priv);
> +	/* register new adapter to i2c module... */
> +	if (i2c_add_numbered_adapter(&priv->adap))
> +		return -1;

return the retval instead of -1?

> +
> +	return 0;
> +}
> +
> +static int __devinit xlr_i2c_probe(struct platform_device *pdev)
> +{
> +	struct xlr_i2c_private  *priv;
> +	struct resource *res;
> +	int ret;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

Initialization looks okay, but you could consider using
devm_request_and_ioremap() and devm_kzalloc. Will need a lot less code.

> +
> +	if (!res) {
> +		ret = -ENXIO;
> +		goto err1;
> +	}
> +
> +	if (!request_mem_region(res->start, XLR_I2C_IO_SIZE, pdev->name)) {
> +		dev_err(&pdev->dev, "request_mem_region failed\n");
> +		ret = -ENOMEM;
> +		goto err1;
> +	}
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		ret = -ENOMEM;
> +		goto err2;
> +	}
> +
> +	priv->adap.dev.parent = &pdev->dev;
> +	priv->iobase = ioremap(res->start, XLR_I2C_IO_SIZE);
> +	if (!priv->iobase) {
> +		ret = -ENOMEM;
> +		goto err3;
> +	}
> +
> +	platform_set_drvdata(pdev, priv);
> +	ret = xlr_i2c_add_bus(priv);
> +
> +	if (ret < 0) {
> +		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
> +		ret = -ENXIO;

return ret instead of overwriting it?

> +		goto err4;
> +	} else
> +		dev_info(&priv->adap.dev, "Added I2C Bus.\n");
> +
> +	return 0;
> +err4:
> +	iounmap(priv->iobase);
> +	platform_set_drvdata(pdev, NULL);
> +err3:
> +	kfree(priv);
> +err2:
> +	release_mem_region(res->start, IORESOURCE_MEM);
> +err1:
> +	return ret;
> +}
> +
> +static int __devexit xlr_i2c_remove(struct platform_device *pdev)
> +{
> +	struct xlr_i2c_private *priv = platform_get_drvdata(pdev);
> +	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	i2c_del_adapter(&priv->adap);
> +	iounmap(priv->iobase);
> +	kfree(priv);
> +	release_mem_region(res->start, IORESOURCE_MEM);
> +	platform_set_drvdata(pdev, NULL);
> +	return 0;
> +}
> +
> +static struct platform_driver xlr_i2c_driver = {
> +	.probe  = xlr_i2c_probe,
> +	.remove = __devexit_p(xlr_i2c_remove),
> +	.driver = {
> +		.owner  = THIS_MODULE,
> +		.name   = "xlr-i2cbus",
> +	},
> +};
> +
> +static int __init xlr_i2c_init(void)
> +{
> +	return platform_driver_register(&xlr_i2c_driver);
> +}
> +
> +static void __exit xlr_i2c_exit(void)
> +{
> +	platform_driver_unregister(&xlr_i2c_driver);
> +}

Use the macro module_platform_driver, please.

> +
> +MODULE_AUTHOR("Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>");
> +MODULE_DESCRIPTION("XLR I2C SMBus driver");
> +MODULE_LICENSE("GPL");

"GPL v2" according to the header.

> +MODULE_ALIAS("platform:xlr-i2cbus");
> +
> +module_init(xlr_i2c_init);
> +module_exit(xlr_i2c_exit);
> -- 
> 1.7.5.4
> 

-- 
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] 17+ messages in thread

* [PATCH UPDATED] Support for Netlogic XLR/XLS I2C controller
       [not found]         ` <20120117232318.GB7774-RazCHl0VsYgkUSuvROHNpA@public.gmane.org>
  2012-01-18  6:28           ` Jayachandran C
@ 2012-01-18 15:33           ` Jayachandran C.
       [not found]             ` <1326900802-27831-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
  1 sibling, 1 reply; 17+ messages in thread
From: Jayachandran C. @ 2012-01-18 15:33 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: khali-PUYAD+kWke1g9hUCZPvPmw, Jayachandran C

From: Jayachandran C <jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>

This version addresses the review comments by Wolfram and Ben to the
previous version (BTW, thanks Wolfram for the detailed review).

The adap.class is set to I2C_CLASS_HWMON, because we have a temparature
sensor on the I2C bus, and I have added a udelay in both the tx and rx
loops so that we are not completely relying on number of retries.

Also as I noted earlier, it is a polling driver, but that is not an issue
in our current usage (and we have many CPUs on-chip).

Ganesan Ramalingam (1):
  i2c: Support for Netlogic XLR/XLS I2C controller.

 drivers/i2c/busses/Kconfig   |   14 ++
 drivers/i2c/busses/Makefile  |    1 +
 drivers/i2c/busses/i2c-xlr.c |  285 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 300 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-xlr.c

-- 
1.7.5.4

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

* [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]             ` <1326900802-27831-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
@ 2012-01-18 15:33               ` Jayachandran C.
       [not found]                 ` <1326900802-27831-2-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Jayachandran C. @ 2012-01-18 15:33 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: khali-PUYAD+kWke1g9hUCZPvPmw, Ganesan Ramalingam, Jayachandran C

From: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>

Add support for the intergrated I2C controller on Netlogic
XLR/XLS MIPS SoC.

The changes are to add a new file i2c/buses/i2c-xlr.c, containing the
i2c bus implementation, and to update i2c/buses/{Kconfig,Makefile} to
add the CONFIG_I2C_XLR option.

Signed-off-by: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
Signed-off-by: Jayachandran C <jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
---
 drivers/i2c/busses/Kconfig   |   14 ++
 drivers/i2c/busses/Makefile  |    1 +
 drivers/i2c/busses/i2c-xlr.c |  285 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 300 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-xlr.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index cbe7a2f..54b0d7d 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -681,6 +681,20 @@ config I2C_XILINX
 	  This driver can also be built as a module.  If so, the module
 	  will be called xilinx_i2c.
 
+config I2C_XLR
+	tristate "XLR I2C support"
+	depends on CPU_XLR
+	help
+	  This driver enables support for the on-chip I2C interface of
+	  the Netlogic XLR/XLS MIPS processors.
+
+	  Say yes to this option if you have a Netlogic XLR/XLS based
+	  board and you need to access the I2C devices (typically the
+	  RTC, sensors, EEPROM) connected to this interface.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-xlr.
+
 config I2C_EG20T
 	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223)"
 	depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index fba6da6..4372dee 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
+obj-$(CONFIG_I2C_XLR)           += i2c-xlr.o
 obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
 
 # External I2C/SMBus adapter drivers
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
new file mode 100644
index 0000000..62307ba
--- /dev/null
+++ b/drivers/i2c/busses/i2c-xlr.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2011, Netlogic Microsystems Inc.
+ * Copyright 2004, Matt Porter <mporter-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+/* XLR I2C REGISTERS */
+#define XLR_I2C_CFG		0x00
+#define XLR_I2C_CLKDIV		0x01
+#define XLR_I2C_DEVADDR		0x02
+#define XLR_I2C_ADDR		0x03
+#define XLR_I2C_DATAOUT		0x04
+#define XLR_I2C_DATAIN		0x05
+#define XLR_I2C_STATUS		0x06
+#define XLR_I2C_STARTXFR	0x07
+#define XLR_I2C_BYTECNT		0x08
+#define XLR_I2C_HDSTATIM	0x09
+
+/* XLR I2C REGISTERS FLAGS */
+#define XLR_I2C_BUS_BUSY	0x01
+#define XLR_I2C_SDOEMPTY	0x02
+#define XLR_I2C_RXRDY		0x04
+#define XLR_I2C_ACK_ERR		0x08
+#define XLR_I2C_ARB_STARTERR	0x30
+
+/* Register Values */
+#define XLR_I2C_CFG_ADDR	0xF8
+#define XLR_I2C_CFG_NOADDR	0xFA
+#define XLR_I2C_STARTXFR_ND	0x02    /* No Data */
+#define XLR_I2C_STARTXFR_RD	0x01    /* Read */
+#define XLR_I2C_STARTXFR_WR	0x00    /* Write */
+
+#define MAX_RETRIES		5000 /* max retries per byte */
+
+/*
+ * On XLR/XLS, we need to use __raw_ IO to read the I2C registers
+ * because they are in the big-endian MMIO area on the SoC.
+ *
+ * The readl/writel implementation on XLR/XLS byteswaps, beacause
+ * those are for its little-endian PCI space (see arch/mips/Kconfig).
+ */
+static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
+{
+	__raw_writel(val, base + reg);
+}
+
+static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
+{
+	return __raw_readl(base + reg);
+}
+
+struct xlr_i2c_private {
+	struct i2c_adapter adap;
+	u32 __iomem *iobase;
+};
+
+static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
+	u8 *buf, u16 addr)
+{
+	struct i2c_adapter *adap = &priv->adap;
+	u32 i2c_status;
+	int pos, retries;
+	u8 offset, nb;
+
+	offset = buf[0];
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
+
+	retries = 0;
+retry:
+	pos = 1;
+	if (len == 1) {
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+				XLR_I2C_STARTXFR_ND);
+	} else {
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+				XLR_I2C_STARTXFR_WR);
+	}
+
+	while (1) {
+		if (retries++ > MAX_RETRIES) {
+			dev_err(&adap->dev, "I2C transmit timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
+
+		if (i2c_status & XLR_I2C_SDOEMPTY) {
+			pos++;
+			retries = 0;
+			nb = (pos < len) ? buf[pos] : 0;
+			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, nb);
+		}
+
+		if (i2c_status & XLR_I2C_ARB_STARTERR)
+			goto retry;
+
+		if (i2c_status & XLR_I2C_ACK_ERR)
+			return -EIO;
+
+		if (i2c_status & XLR_I2C_BUS_BUSY) {
+			udelay(1);
+			continue;
+		}
+
+		if (pos >= len)
+			break;
+	}
+
+	return 0;
+}
+
+static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
+{
+	struct i2c_adapter *adap = &priv->adap;
+	u32 i2c_status;
+	int pos, retries;
+
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+
+	retries = 0;
+	pos = 0;
+retry:
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
+
+	while (1) {
+		if (retries++ > MAX_RETRIES) {
+			dev_err(&adap->dev, "I2C receive timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
+		if (i2c_status & XLR_I2C_RXRDY) {
+			buf[pos++] = (u8)xlr_i2c_rdreg(priv->iobase,
+					XLR_I2C_DATAIN);
+			retries = 0;
+		}
+
+		if (i2c_status & XLR_I2C_ARB_STARTERR)
+			goto retry;
+
+		if (i2c_status & XLR_I2C_ACK_ERR) {
+			dev_err(&adap->dev, "I2C receive ACK error\n");
+			return -EIO;
+		}
+
+		if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
+			break;
+		udelay(1);
+	}
+	return 0;
+}
+
+static int xlr_i2c_xfer(struct i2c_adapter *adap,
+	struct i2c_msg *msgs, int num)
+{
+	struct i2c_msg *msg;
+	int i;
+	int ret = 0;
+	struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
+
+	for (i = 0; ret == 0 && i < num; i++) {
+		msg = &msgs[i];
+		if (msg->flags & I2C_M_RD)
+			ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
+					msg->addr);
+		else
+			ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
+					msg->addr);
+	}
+
+	return (ret != 0) ? ret : num;
+}
+
+static u32 xlr_func(struct i2c_adapter *adap)
+{
+	/* Emulate SMBUS over I2C */
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm xlr_i2c_algo = {
+	.master_xfer	= xlr_i2c_xfer,
+	.functionality	= xlr_func,
+};
+
+static int __devinit xlr_i2c_probe(struct platform_device *pdev)
+{
+	struct xlr_i2c_private  *priv;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->iobase = devm_request_and_ioremap(&pdev->dev, res);
+	if (!priv->iobase) {
+		dev_err(&pdev->dev, "devm_request_and_ioremap failed\n");
+		ret = -EBUSY;
+		goto err1;
+	}
+
+	priv->adap.dev.parent = &pdev->dev;
+	priv->adap.owner	= THIS_MODULE;
+	priv->adap.algo_data	= priv;
+	priv->adap.algo		= &xlr_i2c_algo;
+	priv->adap.nr		= pdev->id;
+	priv->adap.class	= I2C_CLASS_HWMON;
+	snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c");
+
+	platform_set_drvdata(pdev, priv);
+	i2c_set_adapdata(&priv->adap, priv);
+	ret = i2c_add_numbered_adapter(&priv->adap);
+
+	if (ret < 0) {
+		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
+		goto err2;
+	}
+
+	dev_info(&priv->adap.dev, "Added I2C Bus.\n");
+	return 0;
+err2:
+	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
+	devm_iounmap(&pdev->dev, priv->iobase);
+	platform_set_drvdata(pdev, NULL);
+err1:
+	devm_kfree(&pdev->dev, priv);
+	return ret;
+}
+
+static int __devexit xlr_i2c_remove(struct platform_device *pdev)
+{
+	struct xlr_i2c_private *priv;
+	struct resource *res;
+
+	priv = platform_get_drvdata(pdev);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	i2c_del_adapter(&priv->adap);
+	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
+	devm_iounmap(&pdev->dev, priv->iobase);
+	devm_kfree(&pdev->dev, priv);
+
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver xlr_i2c_driver = {
+	.probe  = xlr_i2c_probe,
+	.remove = __devexit_p(xlr_i2c_remove),
+	.driver = {
+		.name   = "xlr-i2cbus",
+		.owner  = THIS_MODULE,
+	},
+};
+
+module_platform_driver(xlr_i2c_driver);
+
+MODULE_AUTHOR("Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>");
+MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:xlr-i2cbus");
-- 
1.7.5.4

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

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]                 ` <1326900802-27831-2-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
@ 2012-01-18 21:27                   ` Wolfram Sang
       [not found]                     ` <20120118212702.GA21576-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Wolfram Sang @ 2012-01-18 21:27 UTC (permalink / raw)
  To: Jayachandran C.
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, khali-PUYAD+kWke1g9hUCZPvPmw,
	Ganesan Ramalingam

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

> +config I2C_XLR
> +	tristate "XLR I2C support"
> +	depends on CPU_XLR
> +	help
> +	  This driver enables support for the on-chip I2C interface of
> +	  the Netlogic XLR/XLS MIPS processors.
> +
> +	  Say yes to this option if you have a Netlogic XLR/XLS based
> +	  board and you need to access the I2C devices (typically the
> +	  RTC, sensors, EEPROM) connected to this interface.

Do you insist on this paragraph?

> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-xlr.
> +
>  config I2C_EG20T
>  	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223)"
>  	depends on PCI
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index fba6da6..4372dee 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
>  obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
>  obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
>  obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
> +obj-$(CONFIG_I2C_XLR)           += i2c-xlr.o

Use tabs here.

>  obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
>  
>  # External I2C/SMBus adapter drivers
> diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
> new file mode 100644
> index 0000000..62307ba
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-xlr.c
> @@ -0,0 +1,285 @@
> +/*
> + * Copyright 2011, Netlogic Microsystems Inc.
> + * Copyright 2004, Matt Porter <mporter-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/init.h>
> +#include <linux/ioport.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +
> +/* XLR I2C REGISTERS */
> +#define XLR_I2C_CFG		0x00
> +#define XLR_I2C_CLKDIV		0x01
> +#define XLR_I2C_DEVADDR		0x02
> +#define XLR_I2C_ADDR		0x03
> +#define XLR_I2C_DATAOUT		0x04
> +#define XLR_I2C_DATAIN		0x05
> +#define XLR_I2C_STATUS		0x06
> +#define XLR_I2C_STARTXFR	0x07
> +#define XLR_I2C_BYTECNT		0x08
> +#define XLR_I2C_HDSTATIM	0x09
> +
> +/* XLR I2C REGISTERS FLAGS */
> +#define XLR_I2C_BUS_BUSY	0x01
> +#define XLR_I2C_SDOEMPTY	0x02
> +#define XLR_I2C_RXRDY		0x04
> +#define XLR_I2C_ACK_ERR		0x08
> +#define XLR_I2C_ARB_STARTERR	0x30
> +
> +/* Register Values */
> +#define XLR_I2C_CFG_ADDR	0xF8
> +#define XLR_I2C_CFG_NOADDR	0xFA
> +#define XLR_I2C_STARTXFR_ND	0x02    /* No Data */
> +#define XLR_I2C_STARTXFR_RD	0x01    /* Read */
> +#define XLR_I2C_STARTXFR_WR	0x00    /* Write */
> +
> +#define MAX_RETRIES		5000 /* max retries per byte */
> +
> +/*
> + * On XLR/XLS, we need to use __raw_ IO to read the I2C registers
> + * because they are in the big-endian MMIO area on the SoC.
> + *
> + * The readl/writel implementation on XLR/XLS byteswaps, beacause
> + * those are for its little-endian PCI space (see arch/mips/Kconfig).
> + */

Good, thanks.

> +static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
> +{
> +	__raw_writel(val, base + reg);
> +}
> +
> +static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
> +{
> +	return __raw_readl(base + reg);
> +}
> +
> +struct xlr_i2c_private {
> +	struct i2c_adapter adap;
> +	u32 __iomem *iobase;
> +};
> +
> +static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
> +	u8 *buf, u16 addr)
> +{
> +	struct i2c_adapter *adap = &priv->adap;
> +	u32 i2c_status;
> +	int pos, retries;
> +	u8 offset, nb;
> +
> +	offset = buf[0];
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
> +
> +	retries = 0;
> +retry:
> +	pos = 1;
> +	if (len == 1) {
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +				XLR_I2C_STARTXFR_ND);
> +	} else {
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +				XLR_I2C_STARTXFR_WR);
> +	}
> +
> +	while (1) {
> +		if (retries++ > MAX_RETRIES) {
> +			dev_err(&adap->dev, "I2C transmit timeout\n");
> +			return -ETIMEDOUT;
> +		}

Still no. A device usually fails after trying for a specific period of time,
not after a number of retries. You need to work with jiffies here and
time_after/time_before. Check drivers/misc/eeprom/at24.c for an example.
Or check the second part of my talk from Prague :)
http://free-electrons.com/blog/elce-2011-videos/

> +
> +		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
> +
> +		if (i2c_status & XLR_I2C_SDOEMPTY) {
> +			pos++;
> +			retries = 0;
> +			nb = (pos < len) ? buf[pos] : 0;
> +			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, nb);
> +		}
> +
> +		if (i2c_status & XLR_I2C_ARB_STARTERR)
> +			goto retry;

This will be an endless loop if the STARTERR condition remains? Also this goto
jumping out of the while loop is not nice. It might help to rearrange the
loops.

> +
> +		if (i2c_status & XLR_I2C_ACK_ERR)
> +			return -EIO;
> +
> +		if (i2c_status & XLR_I2C_BUS_BUSY) {
> +			udelay(1);
> +			continue;
> +		}
> +
> +		if (pos >= len)
> +			break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
> +{
> +	struct i2c_adapter *adap = &priv->adap;
> +	u32 i2c_status;
> +	int pos, retries;
> +
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +
> +	retries = 0;
> +	pos = 0;
> +retry:
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
> +
> +	while (1) {
> +		if (retries++ > MAX_RETRIES) {
> +			dev_err(&adap->dev, "I2C receive timeout\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
> +		if (i2c_status & XLR_I2C_RXRDY) {
> +			buf[pos++] = (u8)xlr_i2c_rdreg(priv->iobase,
> +					XLR_I2C_DATAIN);
> +			retries = 0;
> +		}

comments from above also here.

> +
> +		if (i2c_status & XLR_I2C_ARB_STARTERR)
> +			goto retry;
> +
> +		if (i2c_status & XLR_I2C_ACK_ERR) {
> +			dev_err(&adap->dev, "I2C receive ACK error\n");
> +			return -EIO;
> +		}
> +
> +		if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
> +			break;
> +		udelay(1);
> +	}
> +	return 0;
> +}
> +
> +static int xlr_i2c_xfer(struct i2c_adapter *adap,
> +	struct i2c_msg *msgs, int num)
> +{
> +	struct i2c_msg *msg;
> +	int i;
> +	int ret = 0;
> +	struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
> +
> +	for (i = 0; ret == 0 && i < num; i++) {
> +		msg = &msgs[i];
> +		if (msg->flags & I2C_M_RD)
> +			ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
> +					msg->addr);
> +		else
> +			ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
> +					msg->addr);
> +	}
> +
> +	return (ret != 0) ? ret : num;
> +}
> +
> +static u32 xlr_func(struct i2c_adapter *adap)
> +{
> +	/* Emulate SMBUS over I2C */
> +	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
> +}
> +
> +static struct i2c_algorithm xlr_i2c_algo = {
> +	.master_xfer	= xlr_i2c_xfer,
> +	.functionality	= xlr_func,
> +};
> +
> +static int __devinit xlr_i2c_probe(struct platform_device *pdev)
> +{
> +	struct xlr_i2c_private  *priv;
> +	struct resource *res;
> +	int ret;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENXIO;

You don't have to check res, devm_request_and_ioremap() will do it for you.

> +
> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->iobase = devm_request_and_ioremap(&pdev->dev, res);
> +	if (!priv->iobase) {
> +		dev_err(&pdev->dev, "devm_request_and_ioremap failed\n");
> +		ret = -EBUSY;
> +		goto err1;
> +	}
> +
> +	priv->adap.dev.parent = &pdev->dev;
> +	priv->adap.owner	= THIS_MODULE;
> +	priv->adap.algo_data	= priv;
> +	priv->adap.algo		= &xlr_i2c_algo;
> +	priv->adap.nr		= pdev->id;
> +	priv->adap.class	= I2C_CLASS_HWMON;
> +	snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c");
> +
> +	platform_set_drvdata(pdev, priv);
> +	i2c_set_adapdata(&priv->adap, priv);
> +	ret = i2c_add_numbered_adapter(&priv->adap);
> +
> +	if (ret < 0) {
> +		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
> +		goto err2;
> +	}
> +
> +	dev_info(&priv->adap.dev, "Added I2C Bus.\n");
> +	return 0;
> +err2:
> +	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
> +	devm_iounmap(&pdev->dev, priv->iobase);

You don't need to free devm_* resources. That's the main point of it :)

> +	platform_set_drvdata(pdev, NULL);
> +err1:
> +	devm_kfree(&pdev->dev, priv);
> +	return ret;
> +}
> +
> +static int __devexit xlr_i2c_remove(struct platform_device *pdev)
> +{
> +	struct xlr_i2c_private *priv;
> +	struct resource *res;
> +
> +	priv = platform_get_drvdata(pdev);
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	i2c_del_adapter(&priv->adap);
> +	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
> +	devm_iounmap(&pdev->dev, priv->iobase);
> +	devm_kfree(&pdev->dev, priv);
> +
> +	platform_set_drvdata(pdev, NULL);
> +	return 0;
> +}
> +
> +static struct platform_driver xlr_i2c_driver = {
> +	.probe  = xlr_i2c_probe,
> +	.remove = __devexit_p(xlr_i2c_remove),
> +	.driver = {
> +		.name   = "xlr-i2cbus",
> +		.owner  = THIS_MODULE,
> +	},
> +};
> +
> +module_platform_driver(xlr_i2c_driver);
> +
> +MODULE_AUTHOR("Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>");
> +MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:xlr-i2cbus");
> -- 
> 1.7.5.4
> 

-- 
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] 17+ messages in thread

* RE: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]                     ` <20120118212702.GA21576-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2012-01-19 14:33                       ` Jayachandran C
  2012-01-19 14:42                       ` Jayachandran C.
  1 sibling, 0 replies; 17+ messages in thread
From: Jayachandran C @ 2012-01-19 14:33 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org,
	khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org, Ganesan R

Wolfram Sang [w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org] wrote:
>> +config I2C_XLR
>> +     tristate "XLR I2C support"
>> +     depends on CPU_XLR
>> +     help
>> +       This driver enables support for the on-chip I2C interface of
>> +       the Netlogic XLR/XLS MIPS processors.
>> +
>> +       Say yes to this option if you have a Netlogic XLR/XLS based
>> +       board and you need to access the I2C devices (typically the
>> +       RTC, sensors, EEPROM) connected to this interface.
>
> Do you insist on this paragraph?

Not really :)
I did not see what is wrong here, but taken out anyway.

>> --- a/drivers/i2c/busses/Makefile
>> +++ b/drivers/i2c/busses/Makefile
>> @@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)             += i2c-tegra.o
>>  obj-$(CONFIG_I2C_VERSATILE)  += i2c-versatile.o
>>  obj-$(CONFIG_I2C_OCTEON)     += i2c-octeon.o
>>  obj-$(CONFIG_I2C_XILINX)     += i2c-xiic.o
>> +obj-$(CONFIG_I2C_XLR)           += i2c-xlr.o
>
> Use tabs here.

Done, BTW, CONFIG_I2C_EG20T is also un-sorted and uses spaces.

>> +     retries = 0;
>> +retry:
>> +     pos = 1;
>> +     if (len == 1) {
>> +             xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
>> +                             XLR_I2C_STARTXFR_ND);
>> +     } else {
>> +             xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
>> +             xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
>> +                             XLR_I2C_STARTXFR_WR);
>> +     }
>> +
>> +     while (1) {
>> +             if (retries++ > MAX_RETRIES) {
>> +                     dev_err(&adap->dev, "I2C transmit timeout\n");
>> +                     return -ETIMEDOUT;
>> +             }
>
> Still no. A device usually fails after trying for a specific period of time,
> not after a number of retries. You need to work with jiffies here and
> time_after/time_before. Check drivers/misc/eeprom/at24.c for an example.
> Or check the second part of my talk from Prague :)
> http://free-electrons.com/blog/elce-2011-videos/

The timeout is only for the case where there is a serious issue, all the
normal cases including errors are handled in the code already. The retries
was just a mechanism not to hang the CPU when the hardware is dead. 

The normal transaction take about hundreds of microseconds and the
timeout is 10 times that, which will workout to about a jiffy...

Anyway, I have replaced it with jiffies based timeout.

>> +
>> +             i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
>> +
>> +             if (i2c_status & XLR_I2C_SDOEMPTY) {
>> +                     pos++;
>> +                     retries = 0;
>> +                     nb = (pos < len) ? buf[pos] : 0;
>> +                     xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, nb);
>> +             }
>> +
>> +             if (i2c_status & XLR_I2C_ARB_STARTERR)
>> +                     goto retry;
>
> This will be an endless loop if the STARTERR condition remains? Also this goto
> jumping out of the while loop is not nice. It might help to rearrange the
> loops.

No, the retry count is only reset when there is a successful byte transfer, so the
logic is okay.

[...]
>> +             i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
>> +             if (i2c_status & XLR_I2C_RXRDY) {
>> +                     buf[pos++] = (u8)xlr_i2c_rdreg(priv->iobase,
>> +                                     XLR_I2C_DATAIN);
>> +                     retries = 0;
>> +             }
>
> comments from above also here.

This was okay, but I have fixed up an unrelated issue in the code,
i.e. buf[len] could be written in some cases.

[...]
>> +
>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     if (!res)
>> +             return -ENXIO;
>
> You don't have to check res, devm_request_and_ioremap() will do it for you.

Fixed. Thanks.

>> +     devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
>> +     devm_iounmap(&pdev->dev, priv->iobase);
>
>You don't need to free devm_* resources. That's the main point of it :)

Thanks, fixed this here and in xlr_i2c_remove.  I will follow-up with the
updated patch.

JC.

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

* [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]                     ` <20120118212702.GA21576-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2012-01-19 14:33                       ` Jayachandran C
@ 2012-01-19 14:42                       ` Jayachandran C.
       [not found]                         ` <1326984171-21209-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
  1 sibling, 1 reply; 17+ messages in thread
From: Jayachandran C. @ 2012-01-19 14:42 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, w.sang-bIcnvbaLZ9MEGnE8C9+IrQ
  Cc: khali-PUYAD+kWke1g9hUCZPvPmw, Ganesan Ramalingam, Jayachandran C

From: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>

Add support for the intergrated I2C controller on Netlogic
XLR/XLS MIPS SoC.

The changes are to add a new file i2c/buses/i2c-xlr.c, containing the
i2c bus implementation, and to update i2c/buses/{Kconfig,Makefile} to
add the CONFIG_I2C_XLR option.

Signed-off-by: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
Signed-off-by: Jayachandran C <jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
---
 drivers/i2c/busses/Kconfig   |   10 ++
 drivers/i2c/busses/Makefile  |    1 +
 drivers/i2c/busses/i2c-xlr.c |  279 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 290 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-xlr.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index cbe7a2f..40b7c18 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -681,6 +681,16 @@ config I2C_XILINX
 	  This driver can also be built as a module.  If so, the module
 	  will be called xilinx_i2c.
 
+config I2C_XLR
+	tristate "XLR I2C support"
+	depends on CPU_XLR
+	help
+	  This driver enables support for the on-chip I2C interface of
+	  the Netlogic XLR/XLS MIPS processors.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-xlr.
+
 config I2C_EG20T
 	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223)"
 	depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index fba6da6..a0c644d 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
+obj-$(CONFIG_I2C_XLR)		+= i2c-xlr.o
 obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
 
 # External I2C/SMBus adapter drivers
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
new file mode 100644
index 0000000..ecf3e9e
--- /dev/null
+++ b/drivers/i2c/busses/i2c-xlr.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2011, Netlogic Microsystems Inc.
+ * Copyright 2004, Matt Porter <mporter-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+/* XLR I2C REGISTERS */
+#define XLR_I2C_CFG		0x00
+#define XLR_I2C_CLKDIV		0x01
+#define XLR_I2C_DEVADDR		0x02
+#define XLR_I2C_ADDR		0x03
+#define XLR_I2C_DATAOUT		0x04
+#define XLR_I2C_DATAIN		0x05
+#define XLR_I2C_STATUS		0x06
+#define XLR_I2C_STARTXFR	0x07
+#define XLR_I2C_BYTECNT		0x08
+#define XLR_I2C_HDSTATIM	0x09
+
+/* XLR I2C REGISTERS FLAGS */
+#define XLR_I2C_BUS_BUSY	0x01
+#define XLR_I2C_SDOEMPTY	0x02
+#define XLR_I2C_RXRDY		0x04
+#define XLR_I2C_ACK_ERR		0x08
+#define XLR_I2C_ARB_STARTERR	0x30
+
+/* Register Values */
+#define XLR_I2C_CFG_ADDR	0xF8
+#define XLR_I2C_CFG_NOADDR	0xFA
+#define XLR_I2C_STARTXFR_ND	0x02    /* No Data */
+#define XLR_I2C_STARTXFR_RD	0x01    /* Read */
+#define XLR_I2C_STARTXFR_WR	0x00    /* Write */
+
+#define XLR_I2C_TIMEOUT		5000	/* timeout per byte in usec*/
+
+/*
+ * On XLR/XLS, we need to use __raw_ IO to read the I2C registers
+ * because they are in the big-endian MMIO area on the SoC.
+ *
+ * The readl/writel implementation on XLR/XLS byteswaps, because
+ * those are for its little-endian PCI space (see arch/mips/Kconfig).
+ */
+static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
+{
+	__raw_writel(val, base + reg);
+}
+
+static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
+{
+	return __raw_readl(base + reg);
+}
+
+struct xlr_i2c_private {
+	struct i2c_adapter adap;
+	u32 __iomem *iobase;
+};
+
+static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
+	u8 *buf, u16 addr)
+{
+	struct i2c_adapter *adap = &priv->adap;
+	u32 i2c_status;
+	unsigned long timeout, stoptime;
+	int pos;
+	u8 offset, byte;
+
+	offset = buf[0];
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
+
+	timeout = usecs_to_jiffies(XLR_I2C_TIMEOUT);
+	stoptime = jiffies + timeout;
+	pos = 1;
+retry:
+	if (len == 1) {
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+				XLR_I2C_STARTXFR_ND);
+	} else {
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
+		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
+				XLR_I2C_STARTXFR_WR);
+	}
+
+	while (1) {
+		if (time_after(jiffies, stoptime)) {
+			dev_err(&adap->dev, "I2C transmit timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
+
+		if (i2c_status & XLR_I2C_SDOEMPTY) {
+			pos++;
+			/* need to do a empty dataout after the last byte */
+			byte = (pos < len) ? buf[pos] : 0;
+			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, byte);
+
+			/* reset timeout on successful xmit */
+			stoptime = jiffies + timeout;
+		}
+
+		if (i2c_status & XLR_I2C_ARB_STARTERR)
+			goto retry;
+
+		if (i2c_status & XLR_I2C_ACK_ERR)
+			return -EIO;
+
+		if (i2c_status & XLR_I2C_BUS_BUSY)
+			continue;
+
+		if (pos >= len)
+			break;
+	}
+
+	return 0;
+}
+
+static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
+{
+	struct i2c_adapter *adap = &priv->adap;
+	u32 i2c_status;
+	unsigned long timeout, stoptime;
+	int nbytes;
+	u8 byte;
+
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+
+	timeout = usecs_to_jiffies(XLR_I2C_TIMEOUT);
+	stoptime = jiffies + timeout;
+	nbytes = 0;
+retry:
+	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
+
+	while (1) {
+		if (time_after(jiffies, stoptime)) {
+			dev_err(&adap->dev, "I2C receive timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
+		if (i2c_status & XLR_I2C_RXRDY) {
+			if (nbytes > len)
+				return -EIO;	/* should not happen */
+
+			/* we need to do a dummy datain when nbytes == len */
+			byte = xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
+			if (nbytes < len)
+				buf[nbytes] = byte;
+			nbytes++;
+
+			/* reset timeout on successful read */
+			stoptime = jiffies + timeout;
+		}
+
+		if (i2c_status & XLR_I2C_ARB_STARTERR)
+			goto retry;
+
+		if (i2c_status & XLR_I2C_ACK_ERR) {
+			dev_err(&adap->dev, "I2C receive ACK error\n");
+			return -EIO;
+		}
+
+		if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
+			break;
+	}
+	return 0;
+}
+
+static int xlr_i2c_xfer(struct i2c_adapter *adap,
+	struct i2c_msg *msgs, int num)
+{
+	struct i2c_msg *msg;
+	int i;
+	int ret = 0;
+	struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
+
+	for (i = 0; ret == 0 && i < num; i++) {
+		msg = &msgs[i];
+		if (msg->flags & I2C_M_RD)
+			ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
+					msg->addr);
+		else
+			ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
+					msg->addr);
+	}
+
+	return (ret != 0) ? ret : num;
+}
+
+static u32 xlr_func(struct i2c_adapter *adap)
+{
+	/* Emulate SMBUS over I2C */
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm xlr_i2c_algo = {
+	.master_xfer	= xlr_i2c_xfer,
+	.functionality	= xlr_func,
+};
+
+static int __devinit xlr_i2c_probe(struct platform_device *pdev)
+{
+	struct xlr_i2c_private  *priv;
+	struct resource *res;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->iobase = devm_request_and_ioremap(&pdev->dev, res);
+	if (!priv->iobase) {
+		dev_err(&pdev->dev, "devm_request_and_ioremap failed\n");
+		return -EBUSY;
+	}
+
+	priv->adap.dev.parent = &pdev->dev;
+	priv->adap.owner	= THIS_MODULE;
+	priv->adap.algo_data	= priv;
+	priv->adap.algo		= &xlr_i2c_algo;
+	priv->adap.nr		= pdev->id;
+	priv->adap.class	= I2C_CLASS_HWMON;
+	snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c");
+
+	i2c_set_adapdata(&priv->adap, priv);
+	ret = i2c_add_numbered_adapter(&priv->adap);
+	if (ret < 0) {
+		dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	dev_info(&priv->adap.dev, "Added I2C Bus.\n");
+	return 0;
+}
+
+static int __devexit xlr_i2c_remove(struct platform_device *pdev)
+{
+	struct xlr_i2c_private *priv;
+
+	priv = platform_get_drvdata(pdev);
+	i2c_del_adapter(&priv->adap);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver xlr_i2c_driver = {
+	.probe  = xlr_i2c_probe,
+	.remove = __devexit_p(xlr_i2c_remove),
+	.driver = {
+		.name   = "xlr-i2cbus",
+		.owner  = THIS_MODULE,
+	},
+};
+
+module_platform_driver(xlr_i2c_driver);
+
+MODULE_AUTHOR("Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>");
+MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:xlr-i2cbus");
-- 
1.7.5.4

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

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]                         ` <1326984171-21209-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
@ 2012-01-25 13:40                           ` Wolfram Sang
       [not found]                             ` <20120125134055.GC4755-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Wolfram Sang @ 2012-01-25 13:40 UTC (permalink / raw)
  To: Jayachandran C.
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, khali-PUYAD+kWke1g9hUCZPvPmw,
	Ganesan Ramalingam

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

On Thu, Jan 19, 2012 at 08:12:51PM +0530, Jayachandran C. wrote:
> From: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
> 
> Add support for the intergrated I2C controller on Netlogic
> XLR/XLS MIPS SoC.
> 
> The changes are to add a new file i2c/buses/i2c-xlr.c, containing the
> i2c bus implementation, and to update i2c/buses/{Kconfig,Makefile} to
> add the CONFIG_I2C_XLR option.
> 
> Signed-off-by: Ganesan Ramalingam <ganesanr-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
> Signed-off-by: Jayachandran C <jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>

Please say [PATCH V3] instead of just [PATCH], this helps reviewing.
Also, start a new mail-thread, it might get too messy if 10 different
versions get comments.

> +static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
> +	u8 *buf, u16 addr)
> +{
> +	struct i2c_adapter *adap = &priv->adap;
> +	u32 i2c_status;
> +	unsigned long timeout, stoptime;
> +	int pos;
> +	u8 offset, byte;
> +
> +	offset = buf[0];
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
> +	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
> +
> +	timeout = usecs_to_jiffies(XLR_I2C_TIMEOUT);
> +	stoptime = jiffies + timeout;
> +	pos = 1;
> +retry:
> +	if (len == 1) {
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +				XLR_I2C_STARTXFR_ND);
> +	} else {
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
> +		xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
> +				XLR_I2C_STARTXFR_WR);
> +	}
> +
> +	while (1) {

If you get scheduled away here and return after stoptime, you won't have
checked the status even once. Do something like

		checktime = jiffies;
		i2c_status = ...
		/* check error bits */
		if time_after(checktime, stoptime)
			return -ETIMEDOUT;

An interrupt would be much better, of course.

> +		if (time_after(jiffies, stoptime)) {
> +			dev_err(&adap->dev, "I2C transmit timeout\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
> +
> +		if (i2c_status & XLR_I2C_SDOEMPTY) {
> +			pos++;
> +			/* need to do a empty dataout after the last byte */
> +			byte = (pos < len) ? buf[pos] : 0;
> +			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, byte);
> +
> +			/* reset timeout on successful xmit */
> +			stoptime = jiffies + timeout;
> +		}
> +
> +		if (i2c_status & XLR_I2C_ARB_STARTERR)
> +			goto retry;
> +
> +		if (i2c_status & XLR_I2C_ACK_ERR)
> +			return -EIO;
> +
> +		if (i2c_status & XLR_I2C_BUS_BUSY)
> +			continue;
> +
> +		if (pos >= len)
> +			break;
> +	}
> +
> +	return 0;
> +}

Rest looks okay to me.

Thanks,

   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] 17+ messages in thread

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]                             ` <20120125134055.GC4755-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2012-01-25 13:45                               ` Mark Brown
       [not found]                                 ` <20120125134514.GA2054-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Mark Brown @ 2012-01-25 13:45 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Jayachandran C., linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, khali-PUYAD+kWke1g9hUCZPvPmw,
	Ganesan Ramalingam

On Wed, Jan 25, 2012 at 02:40:55PM +0100, Wolfram Sang wrote:

> Please say [PATCH V3] instead of just [PATCH], this helps reviewing.
> Also, start a new mail-thread, it might get too messy if 10 different
> versions get comments.

...but note that opinions vary on bothering the versioning (it's not
likely to actually annoy anyone though).  The bit about starting a new
thread is important though.

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

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]                                 ` <20120125134514.GA2054-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
@ 2012-01-25 13:52                                   ` Wolfram Sang
       [not found]                                     ` <20120125135236.GD4755-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Wolfram Sang @ 2012-01-25 13:52 UTC (permalink / raw)
  To: Mark Brown
  Cc: Jayachandran C., linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, khali-PUYAD+kWke1g9hUCZPvPmw,
	Ganesan Ramalingam

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

On Wed, Jan 25, 2012 at 01:45:15PM +0000, Mark Brown wrote:
> On Wed, Jan 25, 2012 at 02:40:55PM +0100, Wolfram Sang wrote:
> 
> > Please say [PATCH V3] instead of just [PATCH], this helps reviewing.
> > Also, start a new mail-thread, it might get too messy if 10 different
> > versions get comments.
> 
> ...but note that opinions vary on bothering the versioning (it's not
> likely to actually annoy anyone though).

Huh, never heard of those. When digging old/lost/forgotten patches via
search engines, the versioning does help a lot, for example. Even when
going through huge mailboxes, I'd think this may help to prevent that
old patches are picked? What is the reasoning against versioning?

-- 
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] 17+ messages in thread

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]                                     ` <20120125135236.GD4755-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2012-01-25 14:07                                       ` Jean Delvare
  2012-01-25 14:34                                       ` Mark Brown
  1 sibling, 0 replies; 17+ messages in thread
From: Jean Delvare @ 2012-01-25 14:07 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Mark Brown, Jayachandran C., linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, Ganesan Ramalingam

On Wed, 25 Jan 2012 14:52:36 +0100, Wolfram Sang wrote:
> On Wed, Jan 25, 2012 at 01:45:15PM +0000, Mark Brown wrote:
> > On Wed, Jan 25, 2012 at 02:40:55PM +0100, Wolfram Sang wrote:
> > 
> > > Please say [PATCH V3] instead of just [PATCH], this helps reviewing.
> > > Also, start a new mail-thread, it might get too messy if 10 different
> > > versions get comments.
> > 
> > ...but note that opinions vary on bothering the versioning (it's not
> > likely to actually annoy anyone though).
> 
> Huh, never heard of those. When digging old/lost/forgotten patches via
> search engines, the versioning does help a lot, for example. Even when
> going through huge mailboxes, I'd think this may help to prevent that
> old patches are picked? What is the reasoning against versioning?

Versioning is good, I don't think there's anything to argue about.

-- 
Jean Delvare

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

* Re: [PATCH] i2c: Support for Netlogic XLR/XLS I2C controller.
       [not found]                                     ` <20120125135236.GD4755-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2012-01-25 14:07                                       ` Jean Delvare
@ 2012-01-25 14:34                                       ` Mark Brown
  1 sibling, 0 replies; 17+ messages in thread
From: Mark Brown @ 2012-01-25 14:34 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Jayachandran C., linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	ben-linux-elnMNo+KYs3YtjvyW6yDsg, khali-PUYAD+kWke1g9hUCZPvPmw,
	Ganesan Ramalingam

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

On Wed, Jan 25, 2012 at 02:52:36PM +0100, Wolfram Sang wrote:
> On Wed, Jan 25, 2012 at 01:45:15PM +0000, Mark Brown wrote:

> > ...but note that opinions vary on bothering the versioning (it's not
> > likely to actually annoy anyone though).

> Huh, never heard of those. When digging old/lost/forgotten patches via
> search engines, the versioning does help a lot, for example. Even when
> going through huge mailboxes, I'd think this may help to prevent that

Personally I've never found the version number added anything for any of
that - the fact that it's vX doesn't say anything about vX+1 existing.

> old patches are picked? What is the reasoning against versioning?

I've not seen anyone actively objecting to it but it's certainly not
universal that people want it.  Mostly just due it not being worth the
effort maintaining it, and the occasional confusion it can generate with
new patches having old versions (eg, adding a new patch to an existing
series).  There's also sometimes the depression that comes from seeing
large versions on what ought to be trivial patches.

What does seem to be more of an issue is that tracking the versions of
patches pushes people towards other behaviours which aren't great.  The
one I've really noticed is that quite a few new contributors seem to get
the idea that both the version numbering and the series numbering get
attached to a patch the first time it's posted so even when a series
should be split (eg, because the core bit of the series which everything
depends on got merged) so you see an individual patch posted as patch
3/4 or whatever.

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

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

end of thread, other threads:[~2012-01-25 14:34 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-17 13:48 [PATCH] Support for Netlogic XLR/XLS I2C controller Jayachandran C.
     [not found] ` <1326808100-22540-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
2012-01-17 13:48   ` [PATCH] i2c: " Jayachandran C.
     [not found]     ` <1326808100-22540-2-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
2012-01-17 23:23       ` Ben Dooks
     [not found]         ` <20120117232318.GB7774-RazCHl0VsYgkUSuvROHNpA@public.gmane.org>
2012-01-18  6:28           ` Jayachandran C
2012-01-18 15:33           ` [PATCH UPDATED] " Jayachandran C.
     [not found]             ` <1326900802-27831-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
2012-01-18 15:33               ` [PATCH] i2c: " Jayachandran C.
     [not found]                 ` <1326900802-27831-2-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
2012-01-18 21:27                   ` Wolfram Sang
     [not found]                     ` <20120118212702.GA21576-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-01-19 14:33                       ` Jayachandran C
2012-01-19 14:42                       ` Jayachandran C.
     [not found]                         ` <1326984171-21209-1-git-send-email-jayachandranc-oSioyQM9ZPnuBjGU1YDckgC/G2K4zDHf@public.gmane.org>
2012-01-25 13:40                           ` Wolfram Sang
     [not found]                             ` <20120125134055.GC4755-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-01-25 13:45                               ` Mark Brown
     [not found]                                 ` <20120125134514.GA2054-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2012-01-25 13:52                                   ` Wolfram Sang
     [not found]                                     ` <20120125135236.GD4755-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2012-01-25 14:07                                       ` Jean Delvare
2012-01-25 14:34                                       ` Mark Brown
2012-01-18  9:10       ` Wolfram Sang
  -- strict thread matches above, loose matches on Subject: below --
2011-11-15 17:54 Jayachandran C.
2011-11-16 11:12 ` Shubhrajyoti Datta

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).