public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] mgcoge, mgsuvd: add I2C deblocking mechanism.
@ 2008-09-29  7:55 Heiko Schocher
  2008-09-29  8:57 ` Wolfgang Denk
  2008-10-14 16:30 ` Wolfgang Denk
  0 siblings, 2 replies; 3+ messages in thread
From: Heiko Schocher @ 2008-09-29  7:55 UTC (permalink / raw)
  To: u-boot

As Documented in README, adding a boardspecific Deblocking
mechansim via CFG_I2C_INIT_BOARD for the mgcoge and mgsuvd
board.
This code was originally written by keymile in association
with Anatech and Atmel in 1998. The Code toggels the SCL
until the SCA line goes to High (max. 16 times).
And after this, a start Condition is send.

Signed-off-by: Heiko Schocher <hs@denx.de>
---
 board/keymile/common/common.c |  211 +++++++++++++++++++++++++++++++++++++++++
 board/keymile/mgcoge/Makefile |    2 +-
 drivers/i2c/soft_i2c.c        |   11 ++
 include/configs/mgcoge.h      |    1 +
 include/configs/mgsuvd.h      |    1 +
 5 files changed, 225 insertions(+), 1 deletions(-)
 create mode 100644 board/keymile/common/common.c

diff --git a/board/keymile/common/common.c b/board/keymile/common/common.c
new file mode 100644
index 0000000..a6ed379
--- /dev/null
+++ b/board/keymile/common/common.c
@@ -0,0 +1,211 @@
+/*
+ * (C) Copyright 2008
+ * Heiko Schocher, DENX Software Engineering, hs at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <ioports.h>
+#include <malloc.h>
+
+#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#endif
+
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+#include <i2c.h>
+#endif
+
+#if defined(CONFIG_MGSUVD)
+extern int i2c_mgsuvd_read (void);
+#endif
+
+#if defined(CFG_I2C_INIT_BOARD)
+#define DELAY_ABORT_SEQ		62
+#define DELAY_HALF_PERIOD	(500 / (CFG_I2C_SPEED / 1000))
+
+#if defined(CONFIG_MGCOGE)
+#define SDA_MASK	0x00010000
+#define SCL_MASK	0x00020000
+static void set_pin (int state, unsigned long mask)
+{
+	volatile ioport_t *iop = ioport_addr ((immap_t *)CFG_IMMR, 3);
+
+	if (state)
+		iop->pdat |= (mask);
+	else
+		iop->pdat &= ~(mask);
+
+	iop->pdir |= (mask);
+}
+
+static int get_pin (unsigned long mask)
+{
+	volatile ioport_t *iop = ioport_addr ((immap_t *)CFG_IMMR, 3);
+
+	iop->pdir &= ~(mask);
+	return (0 != (iop->pdat & (mask)));
+}
+
+static void set_sda (int state)
+{
+	set_pin (state, SDA_MASK);
+}
+
+static void set_scl (int state)
+{
+	set_pin (state, SCL_MASK);
+}
+
+static int get_sda (void)
+{
+	return get_pin (SDA_MASK);
+}
+
+static int get_scl (void)
+{
+	return get_pin (SCL_MASK);
+}
+
+#if defined(CONFIG_HARD_I2C)
+static void setports (int gpio)
+{
+	volatile ioport_t *iop = ioport_addr ((immap_t *)CFG_IMMR, 3);
+
+	if (gpio) {
+		iop->ppar &= ~(SDA_MASK | SCL_MASK);
+		iop->podr &= ~(SDA_MASK | SCL_MASK);
+	} else {
+		iop->ppar |= (SDA_MASK | SCL_MASK);
+		iop->pdir &= ~(SDA_MASK | SCL_MASK);
+		iop->podr |= (SDA_MASK | SCL_MASK);
+	}
+}
+#endif
+#endif
+
+#if defined(CONFIG_MGSUVD)
+static void set_sda (int state)
+{
+	I2C_SDA(state);
+}
+
+static void set_scl (int state)
+{
+	I2C_SCL(state);
+}
+
+static int get_sda (void)
+{
+	return i2c_mgsuvd_read ();
+}
+
+static int get_scl (void)
+{
+	int	val;
+
+	*(unsigned short *)(I2C_BASE_DIR) &=  ~SCL_CONF;	
+	udelay (1);
+	val = *(unsigned char *)(I2C_BASE_PORT);
+	
+	return ((val & SCL_BIT) == SCL_BIT);
+}
+
+#endif
+
+static void writeStartSeq (void)
+{
+	set_sda (1);
+	udelay (DELAY_HALF_PERIOD);
+	set_scl (1);
+	udelay (DELAY_HALF_PERIOD);
+	set_sda (0);
+	udelay (DELAY_HALF_PERIOD);
+	set_scl (0);
+	udelay (DELAY_HALF_PERIOD);
+}
+
+/* I2C is a synchronous protocol and resets of the processor in the middle
+   of an access can block the I2C Bus until a powerdown of the full unit is
+   done. This function toggles the SCL until the SCL and SCA line are
+   released, but max. 16 times, after this a I2C start-sequence is sent.
+   This I2C Deblocking mechanism was developed by Keymile in association
+   with Anatech and Atmel in 1998.
+ */
+static int i2c_make_abort (void)
+{
+	int	scl_state = 0;
+	int	sda_state = 0;
+	int	i = 0;
+	int	ret = 0;
+	
+	if (!get_sda ()) {
+		ret = -1;
+		while (i < 16) {
+			i++;
+			set_scl (0);
+			udelay (DELAY_ABORT_SEQ);
+			set_scl (1);
+			udelay (DELAY_ABORT_SEQ);
+			scl_state = get_scl ();
+			sda_state = get_sda ();
+			if (scl_state && sda_state) {
+				ret = 0;
+				break;
+			}
+		}
+	}
+	if (ret == 0) {
+		for (i =0; i < 5; i++) {
+			writeStartSeq ();
+		}
+	}
+	get_sda ();
+	return ret;
+}
+
+/**
+ * i2c_init_board - reset i2c bus. When the board is powercycled during a
+ * bus transfer it might hang; for details see doc/I2C_Edge_Conditions.
+ */
+void i2c_init_board(void)
+{
+#if defined(CONFIG_HARD_I2C)
+	volatile immap_t *immap = (immap_t *)CFG_IMMR ;
+	volatile i2c8260_t *i2c	= (i2c8260_t *)&immap->im_i2c;
+
+	/* disable I2C controller first, otherwhise it thinks we want to    */
+	/* talk to the slave port...                                        */
+	i2c->i2c_i2mod &= ~0x01;
+
+	/* Set the PortPins to GPIO */
+	setports (1);
+#endif
+
+	/* Now run the AbortSequence() */
+	i2c_make_abort ();
+
+#if defined(CONFIG_HARD_I2C)
+	/* Set the PortPins back to use for I2C */
+	setports (0);
+#endif
+}
+#endif
diff --git a/board/keymile/mgcoge/Makefile b/board/keymile/mgcoge/Makefile
index d4087cc..cbf7129 100644
--- a/board/keymile/mgcoge/Makefile
+++ b/board/keymile/mgcoge/Makefile
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk

 LIB	= $(obj)lib$(BOARD).a

-COBJS	:= $(BOARD).o
+COBJS	:= $(BOARD).o ../common/common.o

 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c
index 57736da..983b14b 100644
--- a/drivers/i2c/soft_i2c.c
+++ b/drivers/i2c/soft_i2c.c
@@ -75,7 +75,9 @@ static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = 0;
 /*-----------------------------------------------------------------------
  * Local functions
  */
+#if !defined(CFG_I2C_INIT_BOARD)
 static void  send_reset	(void);
+#endif
 static void  send_start	(void);
 static void  send_stop	(void);
 static void  send_ack	(int);
@@ -83,6 +85,7 @@ static int   write_byte	(uchar byte);
 static uchar read_byte	(int);


+#if !defined(CFG_I2C_INIT_BOARD)
 /*-----------------------------------------------------------------------
  * Send a reset sequence consisting of 9 clocks with the data signal high
  * to clock any confused device back into an idle state.  Also send a
@@ -115,6 +118,7 @@ static void send_reset(void)
 	send_stop();
 	I2C_TRISTATE;
 }
+#endif

 /*-----------------------------------------------------------------------
  * START: High -> Low on SDA while SCL is High
@@ -311,6 +315,12 @@ static uchar read_byte(int ack)
  */
 void i2c_init (int speed, int slaveaddr)
 {
+#if defined(CFG_I2C_INIT_BOARD)
+	/* call board specific i2c bus reset routine before accessing the   */
+	/* environment, which might be in a chip on that bus. For details   */
+	/* about this problem see doc/I2C_Edge_Conditions.                  */
+	i2c_init_board();
+#else
 	/*
 	 * WARNING: Do NOT save speed in a static variable: if the
 	 * I2C routines are called before RAM is initialized (to read
@@ -318,6 +328,7 @@ void i2c_init (int speed, int slaveaddr)
 	 * system will crash.
 	 */
 	send_reset ();
+#endif
 }

 /*-----------------------------------------------------------------------
diff --git a/include/configs/mgcoge.h b/include/configs/mgcoge.h
index bfbbd45..398e092 100644
--- a/include/configs/mgcoge.h
+++ b/include/configs/mgcoge.h
@@ -202,6 +202,7 @@
 #define CONFIG_I2C_MULTI_BUS	1
 #define CONFIG_I2C_CMD_TREE	1
 #define CFG_MAX_I2C_BUS		2
+#define CFG_I2C_INIT_BOARD	1

 /* EEprom support */
 #define CFG_I2C_EEPROM_ADDR_LEN	1
diff --git a/include/configs/mgsuvd.h b/include/configs/mgsuvd.h
index 01433ab..17ad6b4 100644
--- a/include/configs/mgsuvd.h
+++ b/include/configs/mgsuvd.h
@@ -372,6 +372,7 @@
 #define CONFIG_I2C_MULTI_BUS	1
 #define CONFIG_I2C_CMD_TREE	1
 #define CFG_MAX_I2C_BUS		2
+#define CFG_I2C_INIT_BOARD	1

 /* EEprom support */
 #define CFG_I2C_EEPROM_ADDR_LEN	1
-- 
1.5.6.1

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH] mgcoge, mgsuvd: add I2C deblocking mechanism.
  2008-09-29  7:55 [U-Boot] [PATCH] mgcoge, mgsuvd: add I2C deblocking mechanism Heiko Schocher
@ 2008-09-29  8:57 ` Wolfgang Denk
  2008-10-14 16:30 ` Wolfgang Denk
  1 sibling, 0 replies; 3+ messages in thread
From: Wolfgang Denk @ 2008-09-29  8:57 UTC (permalink / raw)
  To: u-boot

Dear Heiko Schocher,

In message <48E089F8.1070809@denx.de> you wrote:
> As Documented in README, adding a boardspecific Deblocking

Which part of the README are you referring to?

> mechansim via CFG_I2C_INIT_BOARD for the mgcoge and mgsuvd
> board.

Are you talking about doc/I2C_Edge_Conditions?

> This code was originally written by keymile in association
> with Anatech and Atmel in 1998. The Code toggels the SCL
> until the SCA line goes to High (max. 16 times).
> And after this, a start Condition is send.


> Signed-off-by: Heiko Schocher <hs@denx.de>
> ---
>  board/keymile/common/common.c |  211 +++++++++++++++++++++++++++++++++++++++++
>  board/keymile/mgcoge/Makefile |    2 +-
>  drivers/i2c/soft_i2c.c        |   11 ++
>  include/configs/mgcoge.h      |    1 +
>  include/configs/mgsuvd.h      |    1 +
>  5 files changed, 225 insertions(+), 1 deletions(-)
>  create mode 100644 board/keymile/common/common.c

Hm... quoting doc/I2C_Edge_Conditions:

... Note that this is NOT necessary when using the bit-banging I2C
driver (common/soft_i2c.c) as this already includes the I2C bus reset
sequence.

Can you please explain what your patch is doing differently, and why
it is needed?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A weak mind is like a microscope, which magnifies trifling things,
but cannot receive great ones.      -- Philip Earl of Chesterfield

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

* [U-Boot] [PATCH] mgcoge, mgsuvd: add I2C deblocking mechanism.
  2008-09-29  7:55 [U-Boot] [PATCH] mgcoge, mgsuvd: add I2C deblocking mechanism Heiko Schocher
  2008-09-29  8:57 ` Wolfgang Denk
@ 2008-10-14 16:30 ` Wolfgang Denk
  1 sibling, 0 replies; 3+ messages in thread
From: Wolfgang Denk @ 2008-10-14 16:30 UTC (permalink / raw)
  To: u-boot

Dear Heiko Schocher,

In message <48E089F8.1070809@denx.de> you wrote:
> As Documented in README, adding a boardspecific Deblocking

documented; board specific deblocking

> mechansim via CFG_I2C_INIT_BOARD for the mgcoge and mgsuvd

mechanism

> board.

boards.

> This code was originally written by keymile in association

Keymile

> with Anatech and Atmel in 1998. The Code toggels the SCL

code

> until the SCA line goes to High (max. 16 times).

high

> And after this, a start Condition is send.

There are many typos in this commit message. Also, the patch does not
apply cleanly:

Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all y
Applying mgcoge, mgsuvd: add I2C deblocking mechanism.
.dotest/patch:140: trailing whitespace.
        *(unsigned short *)(I2C_BASE_DIR) &=  ~SCL_CONF;
.dotest/patch:143: trailing whitespace.

.dotest/patch:174: trailing whitespace.

error: board/keymile/mgcoge/Makefile: does not exist in index
fatal: sha1 information is lacking or useless (include/configs/mgcoge.h).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.
Patch failed at 0005.


Please fix typos, rebase and resubmit.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A student of  probability  soon  realizes  that  by  its  nature  the
billion-to-one  chance  crops  up nine times out of ten, and that the
greatest odds boil down to a double-sided statement: it will  happen,
or it will not.         - Terry Pratchett, _The Dark Side of the Sun_

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

end of thread, other threads:[~2008-10-14 16:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-29  7:55 [U-Boot] [PATCH] mgcoge, mgsuvd: add I2C deblocking mechanism Heiko Schocher
2008-09-29  8:57 ` Wolfgang Denk
2008-10-14 16:30 ` Wolfgang Denk

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