Re: [PATCH 1/3] i2c: xlr: add support for Sigma Designs controller variant

2015-12-15 Thread Wolfram Sang
On Mon, Nov 02, 2015 at 02:03:36AM +, Mans Rullgard wrote:
> Sigma Designs chips use a variant of this controller with the following
> differences:
> 
> - The BUSY bit in the STATUS register is inverted
> - Bit 8 of the CONFIG register must be set
> - The controller can generate interrupts
> 
> This patch adds support for the first two of these.  It also calculates
> and sets the correct clock divisor if a clk is provided.  The bus
> frequency is optionally speficied in the device tree node.

Fixed the "speficied" typo and...

> 
> Signed-off-by: Mans Rullgard 

... applied to for-next, thanks!



signature.asc
Description: Digital signature


Re: [PATCH 1/3] i2c: xlr: add support for Sigma Designs controller variant

2015-11-21 Thread Måns Rullgård
Mans Rullgard  writes:

> Sigma Designs chips use a variant of this controller with the following
> differences:
>
> - The BUSY bit in the STATUS register is inverted
> - Bit 8 of the CONFIG register must be set
> - The controller can generate interrupts
>
> This patch adds support for the first two of these.  It also calculates
> and sets the correct clock divisor if a clk is provided.  The bus
> frequency is optionally speficied in the device tree node.
>
> Signed-off-by: Mans Rullgard 
> ---
>  drivers/i2c/busses/Kconfig   |  6 ++--
>  drivers/i2c/busses/i2c-xlr.c | 81 
> +---
>  2 files changed, 80 insertions(+), 7 deletions(-)

Any comments on these patches?

-- 
Måns Rullgård
m...@mansr.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] i2c: xlr: add support for Sigma Designs controller variant

2015-11-01 Thread Mans Rullgard
Sigma Designs chips use a variant of this controller with the following
differences:

- The BUSY bit in the STATUS register is inverted
- Bit 8 of the CONFIG register must be set
- The controller can generate interrupts

This patch adds support for the first two of these.  It also calculates
and sets the correct clock divisor if a clk is provided.  The bus
frequency is optionally speficied in the device tree node.

Signed-off-by: Mans Rullgard 
---
 drivers/i2c/busses/Kconfig   |  6 ++--
 drivers/i2c/busses/i2c-xlr.c | 81 +---
 2 files changed, 80 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index f764e3a..fdedf59 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -944,11 +944,11 @@ config I2C_XILINX
  will be called xilinx_i2c.
 
 config I2C_XLR
-   tristate "XLR I2C support"
-   depends on CPU_XLR
+   tristate "Netlogic XLR and Sigma Designs I2C support"
+   depends on CPU_XLR || ARCH_TANGOX
help
  This driver enables support for the on-chip I2C interface of
- the Netlogic XLR/XLS MIPS processors.
+ the Netlogic XLR/XLS MIPS processors and Sigma Designs SOCs.
 
  This driver can also be built as a module.  If so, the module
  will be called i2c-xlr.
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
index 8b36bcf..10fb916 100644
--- a/drivers/i2c/busses/i2c-xlr.c
+++ b/drivers/i2c/busses/i2c-xlr.c
@@ -17,6 +17,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 /* XLR I2C REGISTERS */
 #define XLR_I2C_CFG0x00
@@ -63,11 +65,23 @@ static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned 
int reg)
return __raw_readl(base + reg);
 }
 
+struct xlr_i2c_config {
+   u32 status_busy;/* value of STATUS[0] when busy */
+   u32 cfg_extra;  /* extra CFG bits to set */
+};
+
 struct xlr_i2c_private {
struct i2c_adapter adap;
u32 __iomem *iobase;
+   const struct xlr_i2c_config *cfg;
+   struct clk *clk;
 };
 
+static int xlr_i2c_busy(struct xlr_i2c_private *priv, u32 status)
+{
+   return (status & XLR_I2C_BUS_BUSY) == priv->cfg->status_busy;
+}
+
 static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
u8 *buf, u16 addr)
 {
@@ -80,7 +94,8 @@ static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
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_CFG,
+   XLR_I2C_CFG_ADDR | priv->cfg->cfg_extra);
xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
 
timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
@@ -121,7 +136,7 @@ retry:
if (i2c_status & XLR_I2C_ACK_ERR)
return -EIO;
 
-   if ((i2c_status & XLR_I2C_BUS_BUSY) == 0 && pos >= len)
+   if (!xlr_i2c_busy(priv, i2c_status) && pos >= len)
return 0;
}
dev_err(&adap->dev, "I2C transmit timeout\n");
@@ -136,7 +151,8 @@ static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 
len, u8 *buf, u16 addr)
int nbytes, timedout;
u8 byte;
 
-   xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
+   xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
+   XLR_I2C_CFG_NOADDR | priv->cfg->cfg_extra);
xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
 
@@ -174,7 +190,7 @@ retry:
if (i2c_status & XLR_I2C_ACK_ERR)
return -EIO;
 
-   if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
+   if (!xlr_i2c_busy(priv, i2c_status))
return 0;
}
 
@@ -190,6 +206,10 @@ static int xlr_i2c_xfer(struct i2c_adapter *adap,
int ret = 0;
struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
 
+   ret = clk_enable(priv->clk);
+   if (ret)
+   return ret;
+
for (i = 0; ret == 0 && i < num; i++) {
msg = &msgs[i];
if (msg->flags & I2C_M_RD)
@@ -200,6 +220,8 @@ static int xlr_i2c_xfer(struct i2c_adapter *adap,
msg->addr);
}
 
+   clk_disable(priv->clk);
+
return (ret != 0) ? ret : num;
 }
 
@@ -214,22 +236,70 @@ static struct i2c_algorithm xlr_i2c_algo = {
.functionality  = xlr_func,
 };
 
+static const struct xlr_i2c_config xlr_i2c_config_default = {
+   .status_busy= XLR_I2C_BUS_BUSY,
+   .cfg_extra  = 0,
+};
+
+static const struct xlr_i2c_config xlr_i2c_config_tangox = {
+   .status_busy= 0,
+   .cfg_extra  = 1 << 8,
+};
+
+static const struct of_device_id xlr_i2c_dt_ids[] = {
+   {
+