patch: add gt64260 I2C read function to bootwrapper

Dale Farnsworth dale at farnsworth.org
Sat Mar 15 17:32:06 EST 2003


This patch adds a polled read-only I2C driver for the gt64260
that can be used by board-specific bootwrapper code.

Thanks,
-Dale

include/asm-ppc/gt64260_defs.h:
Add definitions for the I2C registers.

arch/ppc/boot/simple/gt64260_iic.c:
Add gt64260_iic_read() for reading I2C devices.

===== include/asm-ppc/gt64260_defs.h 1.11 vs edited =====
--- 1.11/include/asm-ppc/gt64260_defs.h	Fri Feb 28 10:31:00 2003
+++ edited/include/asm-ppc/gt64260_defs.h	Fri Mar 14 18:16:45 2003
@@ -1108,7 +1108,31 @@
  *****************************************************************************
  */

-/* FIXME: fill in */
+#define GT64260_I2C_ADDR				0xc000
+#define GT64260_I2C_EX_ADDR				0xc010
+#define GT64260_I2C_DATA				0xc004
+#define GT64260_I2C_CONTROL				0xc008
+#define GT64260_I2C_STATUS				0xc00c
+#define GT64260_I2C_BAUD_RATE				0xc00c
+#define GT64260_I2C_RESET				0xc01c
+
+#define GT64260_I2C_ACK_BIT				(1<<2)
+#define GT64260_I2C_IFLG_BIT				(1<<3)
+#define GT64260_I2C_STOP_BIT				(1<<4)
+#define GT64260_I2C_START_BIT				(1<<5)
+#define GT64260_I2C_ENABLE_BIT				(1<<6)
+#define GT64260_I2C_INT_ENABLE_BIT			(1<<7)
+
+#define GT64260_I2C_DATA_READ_BIT			0x01
+
+#define GT64260_I2C_STATUS_SENT_START			0x08
+#define GT64260_I2C_STATUS_RESENT_START			0x10
+#define GT64260_I2C_STATUS_WRITE_ADDR_ACK		0x18
+#define GT64260_I2C_STATUS_WRITE_ACK			0x28
+#define GT64260_I2C_STATUS_READ_ADDR_ACK		0x40
+#define GT64260_I2C_STATUS_READ_ACK			0x50
+#define GT64260_I2C_STATUS_READ_NO_ACK			0x58
+#define GT64260_I2C_STATUS_IDLE				0xf8


 /*
===== arch/ppc/boot/simple/gt64260_iic.c null vs new =====
--- null/arch/ppc/boot/simple/gt64260_iic.c	1969-12-31 17:00:00.000000000 -0700
+++ new/arch/ppc/boot/simple/gt64260_iic.c	2003-03-14 18:44:50.000000000 -0700
@@ -0,0 +1,186 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * arch/ppc/boot/simple/gt64260_iic.c
+ *
+ * Bootloader version of the i2c driver for the GT64260[A].
+ *
+ * Author: Dale Farnsworth <dfarnsworth at mvista.com>
+ *
+ * 2003 (c) MontaVista, Software, Inc.  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/config.h>
+#include <linux/types.h>
+#include <asm/gt64260_defs.h>
+
+
+extern void udelay(long);
+
+#ifdef	CONFIG_GT64260_NEW_BASE
+static u32	gt64260_base = CONFIG_GT64260_NEW_REG_BASE;
+#else
+static u32	gt64260_base = CONFIG_GT64260_ORIG_REG_BASE;
+#endif
+
+inline unsigned
+gt64260_in_le32(volatile unsigned *addr)
+{
+	unsigned ret;
+
+	__asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) :
+				     "r" (addr), "m" (*addr));
+	return ret;
+}
+
+inline void
+gt64260_out_le32(volatile unsigned *addr, int val)
+{
+	__asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
+				     "r" (val), "r" (addr));
+}
+
+#define GT64260_REG_READ(offs)						\
+	(gt64260_in_le32((volatile uint *)(gt64260_base + (offs))))
+#define GT64260_REG_WRITE(offs, d)					\
+        (gt64260_out_le32((volatile uint *)(gt64260_base + (offs)), (int)(d)))
+
+#define READ_ADDR()		(GT64260_REG_READ(GT64260_I2C_ADDR) & 0xff)
+#define READ_EX_ADDR()		(GT64260_REG_READ(GT64260_I2C_EX_ADDR) & 0xff)
+#define READ_DATA()		(GT64260_REG_READ(GT64260_I2C_DATA) & 0xff)
+#define READ_CONTROL()		(GT64260_REG_READ(GT64260_I2C_CONTROL) & 0xff)
+#define READ_STATUS()		(GT64260_REG_READ(GT64260_I2C_STATUS) & 0xff)
+
+#define WRITE_ADDR(d)		GT64260_REG_WRITE(GT64260_I2C_ADDR, (d))
+#define WRITE_EX_ADDR(d)	GT64260_REG_WRITE(GT64260_I2C_EX_ADDR, (d))
+#define WRITE_DATA(d)		GT64260_REG_WRITE(GT64260_I2C_DATA, (d))
+#define WRITE_CONTROL(d)	GT64260_REG_WRITE(GT64260_I2C_CONTROL, (d))
+#define WRITE_BAUD_RATE(d)	GT64260_REG_WRITE(GT64260_I2C_BAUD_RATE, (d))
+#define WRITE_RESET(d)		GT64260_REG_WRITE(GT64260_I2C_RESET, (d))
+
+static int
+wait_for_status(int wanted)
+{
+	int i;
+	int status;
+
+	for (i=0; i<1000; i++) {	/* the highest I've seen is 20 */
+		udelay(10);
+		status = READ_STATUS();
+		if (status == wanted)
+			return status;
+	}
+	return -status;
+}
+
+static int
+iic_control(int control, int status)
+{
+    	WRITE_CONTROL(control);
+	return wait_for_status(status);
+}
+
+static int
+iic_read_byte(int control, int status)
+{
+    	WRITE_CONTROL(control);
+	if (wait_for_status(status) < 0)
+		return -1;
+	return READ_DATA();
+}
+
+static int
+iic_write_byte(int data, int control, int status)
+{
+	WRITE_DATA(data & 0xff);
+    	WRITE_CONTROL(control);
+	return wait_for_status(status);
+}
+
+int
+gt64260_iic_read(uint devaddr, u8 *buf, uint offset, uint count)
+{
+	int i;
+	int data;
+	int control;
+	int status;
+
+	/*
+	 * send start
+	 */
+	control = GT64260_I2C_START_BIT|GT64260_I2C_ENABLE_BIT;
+	status = GT64260_I2C_STATUS_SENT_START;
+	if (iic_control(control, status) < 0)
+		return -1;
+
+	/*
+	 * select device for writing
+	 */
+	data = devaddr & ~GT64260_I2C_DATA_READ_BIT;
+	control = GT64260_I2C_ENABLE_BIT;
+	status = GT64260_I2C_STATUS_WRITE_ADDR_ACK;
+	if (iic_write_byte(data, control, status) < 0)
+		return -1;
+
+	/*
+	 * send offset of data
+	 */
+	control = GT64260_I2C_ENABLE_BIT;
+	status = GT64260_I2C_STATUS_WRITE_ACK;
+	if (iic_write_byte(offset >> 8, control, status) < 0)
+		return -1;
+	if (iic_write_byte(offset, control, status) < 0)
+		return -1;
+
+	/*
+	 * resend start
+	 */
+	control = GT64260_I2C_START_BIT|GT64260_I2C_ENABLE_BIT;
+	status = GT64260_I2C_STATUS_RESENT_START;
+	if (iic_control(control, status) < 0)
+		return -1;
+
+	/*
+	 * select device for reading
+	 */
+	data = devaddr | GT64260_I2C_DATA_READ_BIT;
+	control = GT64260_I2C_ENABLE_BIT;
+	status = GT64260_I2C_STATUS_READ_ADDR_ACK;
+	if (iic_write_byte(data, control, status) < 0)
+		return -1;
+
+	/*
+	 * read all but last byte of data
+	 */
+	for (i=1; i<count; i++) {
+		control = GT64260_I2C_ACK_BIT|GT64260_I2C_ENABLE_BIT;
+		status = GT64260_I2C_STATUS_READ_ACK;
+		data = iic_read_byte(control, status);
+		if (data < 0)
+			return -1;
+		*buf++ = data;
+	}
+
+	/*
+	 * read last byte of data
+	 */
+	control = GT64260_I2C_ENABLE_BIT;
+	status = GT64260_I2C_STATUS_READ_NO_ACK;
+	data = iic_read_byte(control, status);
+	if (data < 0)
+		return -1;
+	*buf++ = data;
+
+	/*
+	 * send stop
+	 */
+	control = GT64260_I2C_STOP_BIT|GT64260_I2C_ENABLE_BIT;
+	status = GT64260_I2C_STATUS_IDLE;
+	if (iic_control(control, status) < 0)
+		return -1;
+
+	return count;
+}

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/





More information about the Linuxppc-dev mailing list