All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/5] video: mb862xx: add support for controller's I2C bus adapter
@ 2011-05-13 15:54 Anatolij Gustschin
  2011-05-24  7:23 ` Paul Mundt
  2011-05-24  7:45 ` [PATCH 4/5] video: mb862xx: add support for controller's I2C Anatolij Gustschin
  0 siblings, 2 replies; 3+ messages in thread
From: Anatolij Gustschin @ 2011-05-13 15:54 UTC (permalink / raw)
  To: linux-fbdev

Add adapter driver for I2C adapter in Coral-P(A)/Lime GDCs.
So we can easily access devices on controller's I2C bus using
i2c-dev interface.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 drivers/video/mb862xx/Makefile      |    2 +-
 drivers/video/mb862xx/mb862xx-i2c.c |  168 +++++++++++++++++++++++++++++++++++
 drivers/video/mb862xx/mb862xx_reg.h |   21 +++++
 drivers/video/mb862xx/mb862xxfb.c   |    2 +
 drivers/video/mb862xx/mb862xxfb.h   |    3 +
 5 files changed, 195 insertions(+), 1 deletions(-)
 create mode 100644 drivers/video/mb862xx/mb862xx-i2c.c

diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile
index d777771..3a36c45 100644
--- a/drivers/video/mb862xx/Makefile
+++ b/drivers/video/mb862xx/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the MB862xx framebuffer driver
 #
 
-obj-$(CONFIG_FB_MB862XX)	:= mb862xxfb.o mb862xxfb_accel.o
+obj-$(CONFIG_FB_MB862XX)	:= mb862xxfb.o mb862xxfb_accel.o mb862xx-i2c.o
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c
new file mode 100644
index 0000000..d50cc71
--- /dev/null
+++ b/drivers/video/mb862xx/mb862xx-i2c.c
@@ -0,0 +1,168 @@
+/*
+ * Coral-P(A)/Lime I2C adapter driver
+ *
+ * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+
+#include "mb862xxfb.h"
+#include "mb862xx_reg.h"
+
+static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+	u32 reg;
+
+	do {
+		reg = inreg(i2c, GC_I2C_BCR);
+		if (reg & (I2C_INT | I2C_BER))
+			break;
+	} while (1);
+
+	return (reg & I2C_BER) ? 0 : 1;
+}
+
+static int mb862xx_i2c_do_address(struct i2c_adapter *adap, int addr)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+
+	outreg(i2c, GC_I2C_DAR, addr);
+	outreg(i2c, GC_I2C_CCR, I2C_CLOCK_AND_ENABLE);
+	outreg(i2c, GC_I2C_BCR, par->i2c_rs ? I2C_REPEATED_START : I2C_START);
+	if (!mb862xx_i2c_wait_event(adap))
+		return -EIO;
+	par->i2c_rs = !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
+	return par->i2c_rs;
+}
+
+static int mb862xx_i2c_write_byte(struct i2c_adapter *adap, u8 byte)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+
+	outreg(i2c, GC_I2C_DAR, byte);
+	outreg(i2c, GC_I2C_BCR, I2C_START);
+	if (!mb862xx_i2c_wait_event(adap))
+		return -EIO;
+	return !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
+}
+
+static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+
+	outreg(i2c, GC_I2C_BCR, I2C_START | (last ? 0 : I2C_ACK));
+	if (!mb862xx_i2c_wait_event(adap))
+		return 0;
+	*byte = inreg(i2c, GC_I2C_DAR);
+	return 1;
+}
+
+void mb862xx_i2c_stop(struct i2c_adapter *adap)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+
+	outreg(i2c, GC_I2C_BCR, I2C_STOP);
+	outreg(i2c, GC_I2C_CCR, I2C_DISABLE);
+	par->i2c_rs = 0;
+}
+
+static int mb862xx_i2c_read(struct i2c_adapter *adap, struct i2c_msg *m)
+{
+	int i, ret = 0;
+	int last = m->len - 1;
+
+	for (i = 0; i < m->len; i++) {
+		if (!mb862xx_i2c_read_byte(adap, &m->buf[i], i = last)) {
+			ret = -EIO;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int mb862xx_i2c_write(struct i2c_adapter *adap, struct i2c_msg *m)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < m->len; i++) {
+		if (!mb862xx_i2c_write_byte(adap, m->buf[i])) {
+			ret = -EIO;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int mb862xx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			int num)
+{
+	struct mb862xxfb_par *par = adap->algo_data;
+	struct i2c_msg *m;
+	int addr;
+	int i = 0, err = 0;
+
+	dev_dbg(par->dev, "%s: %d msgs\n", __func__, num);
+
+	for (i = 0; i < num; i++) {
+		m = &msgs[i];
+		if (!m->len) {
+			dev_dbg(par->dev, "%s: null msgs\n", __func__);
+			continue;
+		}
+		addr = m->addr;
+		if (m->flags & I2C_M_RD)
+			addr |= 1;
+
+		err = mb862xx_i2c_do_address(adap, addr);
+		if (err < 0)
+			break;
+		if (m->flags & I2C_M_RD)
+			err = mb862xx_i2c_read(adap, m);
+		else
+			err = mb862xx_i2c_write(adap, m);
+	}
+
+	if (i)
+		mb862xx_i2c_stop(adap);
+
+	return (err < 0) ? err : i;
+}
+
+static u32 mb862xx_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static const struct i2c_algorithm mb862xx_algo = {
+	.master_xfer	= mb862xx_xfer,
+	.functionality	= mb862xx_func,
+};
+
+static struct i2c_adapter mb862xx_i2c_adapter = {
+	.name		= "MB862xx I2C adapter",
+	.algo		= &mb862xx_algo,
+	.owner		= THIS_MODULE,
+};
+
+int mb862xx_i2c_init(struct mb862xxfb_par *par)
+{
+	int ret;
+
+	mb862xx_i2c_adapter.algo_data = par;
+	par->adap = &mb862xx_i2c_adapter;
+
+	ret = i2c_add_adapter(par->adap);
+	if (ret < 0) {
+		dev_err(par->dev, "failed to add %s\n",
+			mb862xx_i2c_adapter.name);
+	}
+	return ret;
+}
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h
index 737fc01..5784b01 100644
--- a/drivers/video/mb862xx/mb862xx_reg.h
+++ b/drivers/video/mb862xx/mb862xx_reg.h
@@ -80,6 +80,27 @@
 
 #define GC_DISP_REFCLK_400	400
 
+/* I2C */
+#define GC_I2C_BSR		0x00000000	/* BSR */
+#define GC_I2C_BCR		0x00000004	/* BCR */
+#define GC_I2C_CCR		0x00000008	/* CCR */
+#define GC_I2C_ADR		0x0000000C	/* ADR */
+#define GC_I2C_DAR		0x00000010	/* DAR */
+
+#define I2C_DISABLE		0x00000000
+#define I2C_STOP		0x00000000
+#define I2C_START		0x00000010
+#define I2C_REPEATED_START	0x00000030
+#define I2C_CLOCK_AND_ENABLE	0x0000003f
+#define I2C_READY		0x01
+#define I2C_INT			0x01
+#define I2C_INTE		0x02
+#define I2C_ACK			0x08
+#define I2C_BER			0x80
+#define I2C_BEIE		0x40
+#define I2C_TRX			0x80
+#define I2C_LRB			0x10
+
 /* Carmine specific */
 #define MB86297_DRAW_BASE		0x00020000
 #define MB86297_DISP0_BASE		0x00100000
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index ffb6a2c..a9779f8 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -772,6 +772,8 @@ static int coralp_init(struct mb862xxfb_par *par)
 	} else {
 		return -ENODEV;
 	}
+
+	mb862xx_i2c_init(par);
 	return 0;
 }
 
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h
index d7e7cb7..f0f57ea 100644
--- a/drivers/video/mb862xx/mb862xxfb.h
+++ b/drivers/video/mb862xx/mb862xxfb.h
@@ -57,11 +57,14 @@ struct mb862xxfb_par {
 	unsigned int		refclk;		/* disp. reference clock */
 	struct mb862xx_gc_mode	*gc_mode;	/* GDC mode init data */
 	int			pre_init;	/* don't init display if 1 */
+	struct i2c_adapter	*adap;		/* GDC I2C bus adapter */
+	int			i2c_rs;
 
 	u32			pseudo_palette[16];
 };
 
 extern void mb862xxfb_init_accel(struct fb_info *info, int xres);
+extern int mb862xx_i2c_init(struct mb862xxfb_par *par);
 
 #if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC)
 #error	"Select Lime GDC or CoralP/Carmine support, but not both together"
-- 
1.7.1


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

* Re: [PATCH 4/5] video: mb862xx: add support for controller's I2C bus adapter
  2011-05-13 15:54 [PATCH 4/5] video: mb862xx: add support for controller's I2C bus adapter Anatolij Gustschin
@ 2011-05-24  7:23 ` Paul Mundt
  2011-05-24  7:45 ` [PATCH 4/5] video: mb862xx: add support for controller's I2C Anatolij Gustschin
  1 sibling, 0 replies; 3+ messages in thread
From: Paul Mundt @ 2011-05-24  7:23 UTC (permalink / raw)
  To: linux-fbdev

On Fri, May 13, 2011 at 05:54:48PM +0200, Anatolij Gustschin wrote:
> Add adapter driver for I2C adapter in Coral-P(A)/Lime GDCs.
> So we can easily access devices on controller's I2C bus using
> i2c-dev interface.
> 
> Signed-off-by: Anatolij Gustschin <agust@denx.de>

I don't see anything in the Kconfig that prevents this from being built
with CONFIG_I2C=n, have you tested this case?

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

* Re: [PATCH 4/5] video: mb862xx: add support for controller's I2C
  2011-05-13 15:54 [PATCH 4/5] video: mb862xx: add support for controller's I2C bus adapter Anatolij Gustschin
  2011-05-24  7:23 ` Paul Mundt
@ 2011-05-24  7:45 ` Anatolij Gustschin
  1 sibling, 0 replies; 3+ messages in thread
From: Anatolij Gustschin @ 2011-05-24  7:45 UTC (permalink / raw)
  To: linux-fbdev

On Tue, 24 May 2011 16:23:44 +0900
Paul Mundt <lethal@linux-sh.org> wrote:

> On Fri, May 13, 2011 at 05:54:48PM +0200, Anatolij Gustschin wrote:
> > Add adapter driver for I2C adapter in Coral-P(A)/Lime GDCs.
> > So we can easily access devices on controller's I2C bus using
> > i2c-dev interface.
> > 
> > Signed-off-by: Anatolij Gustschin <agust@denx.de>
> 
> I don't see anything in the Kconfig that prevents this from being built
> with CONFIG_I2C=n, have you tested this case?

No. Thanks for pointing this out, I'll fix it.

BR,
Anatolij

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

end of thread, other threads:[~2011-05-24  7:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-13 15:54 [PATCH 4/5] video: mb862xx: add support for controller's I2C bus adapter Anatolij Gustschin
2011-05-24  7:23 ` Paul Mundt
2011-05-24  7:45 ` [PATCH 4/5] video: mb862xx: add support for controller's I2C Anatolij Gustschin

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