[U-Boot] [patch V3] [1/3] PNX8181 SOC support

Jürgen Schöw juergen at Schoew.net
Sun Jan 4 22:54:29 CET 2009


 cpu/arm926ejs/pnx8181/Makefile     |   45 +++
 cpu/arm926ejs/pnx8181/timer.c      |  141 ++++++++
 drivers/i2c/Makefile               |    1 +
 drivers/i2c/pnx8181_i2c.c          |  304 +++++++++++++++++

diff --git a/cpu/arm926ejs/pnx8181/Makefile b/cpu/arm926ejs/pnx8181/Makefile
new file mode 100644
index 0000000..b34d9e8
--- /dev/null
+++ b/cpu/arm926ejs/pnx8181/Makefile
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd 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 $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).a
+
+COBJS	= timer.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/arm926ejs/pnx8181/timer.c b/cpu/arm926ejs/pnx8181/timer.c
new file mode 100644
index 0000000..585aede
--- /dev/null
+++ b/cpu/arm926ejs/pnx8181/timer.c
@@ -0,0 +1,141 @@
+/*
+ * pnx8181 SOC timer routines
+ *
+ * (C) Copyright 2007-2009, emlix GmbH, Germany
+ * Juergen Schoew <js at emlix.com>
+ *
+ * (C) Copyright 2008, DSPG Technologies GmbH, Germany
+ * (C) Copyright 2007, NXP Semiconductors Germany GmbH
+ * Matthias Wenzel, <nxp at mazzoo.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 <asm/io.h>
+
+/*
+ * timer without interrupts
+ */
+/* timer */
+#define PNX8181_SCTU1_BASE	0xC2102000
+#define PNX8181_SCTU2_BASE	0xC2103000
+
+#define PNX8181_SCTU_TIMxCR	0x00
+#define PNX8181_SCTU_TIMxRR	0x04
+#define PNX8181_SCTU_TIMxWR	0x08
+#define PNX8181_SCTU_TIMxC0	0x0c
+#define PNX8181_SCTU_TIMxC1	0x10
+#define PNX8181_SCTU_TIMxC2	0x14
+#define PNX8181_SCTU_TIMxC3	0x18
+#define PNX8181_SCTU_TIMxSR	0x1c
+#define PNX8181_SCTU_TIMxPR	0x20
+
+/*
+ * U-Boot expects a 32 bit timer, running at CONFIG_SYS_HZ
+ * Keep total timer count to avoid losing decrements < div_timer
+ */
+
+/* U-Boot ticks since startup */
+static ulong timestamp;
+static ulong last_timer_read;
+
+/*
+ * starts up a counter
+ */
+void timer_init(void)
+{
+	/* set prescaler to have timer run at 64 kHz */
+	writeb(0x00, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxPR));
+
+	/* timer reload value = 0xffff - 13824, overflow @ 1kHz */
+	writew(0xca00, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxRR));
+
+	/* timer has no interrupt, run */
+	writew(0x0001, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxCR));
+
+	/* init the timestamp */
+	reset_timer_masked();
+}
+
+ulong get_timer(ulong base_ticks)
+{
+	return get_timer_masked() - base_ticks;
+}
+
+/*
+ * converts the timer reading to U-Boot ticks
+ * the timestamp is the number of ticks since reset
+ */
+ulong get_timer_masked(void)
+{
+	/* get current count */
+	ulong now = readw((void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxWR));
+
+	if (now < last_timer_read)
+		timestamp += 13824;
+	last_timer_read = now;
+
+	/*
+	 * FIXME	this value is empirical!
+	 *		for some reason the calculated values are way to fast
+	 */
+	return (timestamp + now) / 64;
+}
+
+/*
+ * timer without interrupts
+ */
+void reset_timer(void)
+{
+	reset_timer_masked();
+}
+
+
+/* busy-loop spin-delay */
+void sdelay(unsigned long usec)
+{
+	ulong i, tmp;
+	tmp = 42;
+	for (i = 0 ; i < usec*3 ; i++)
+		/* avoid compiler optimisation */
+		tmp = -tmp;
+}
+
+/* delay usec useconds */
+void udelay(unsigned long usec)
+{
+	ulong tmo, tmp;
+
+	/* Convert to U-Boot ticks */
+	tmo  = usec / 1500;
+
+	tmp  = get_timer_masked();	/* get current timestamp */
+	tmo += tmp;			/* form target timestamp */
+
+	/* loop till event */
+	while (get_timer_masked() < tmo)
+		;
+}
+
+void reset_timer_masked(void)
+{
+	/* start "advancing" time stamp from 0 */
+	timestamp = 0L;
+}
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 6079c05..ef457a5 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
 COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o
 COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
+COBJS-$(CONFIG_PNX8181_I2C) += pnx8181_i2c.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/i2c/pnx8181_i2c.c b/drivers/i2c/pnx8181_i2c.c
new file mode 100644
index 0000000..75a76a4
--- /dev/null
+++ b/drivers/i2c/pnx8181_i2c.c
@@ -0,0 +1,304 @@
+/*
+ * (C) Copyright 2008-2009, emlix GmbH, Germany
+ * Juergen Schoew <js at emlix.com>
+ *
+ * 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 <config.h>
+#include <common.h>
+#include <asm/io.h>
+
+#define I2C_TIMEOUT		10000
+#define I2C_DELAY		10
+
+#define ARM_VPB1_BASE_ADDR	0xC2000000
+#define ARM_VPB3_BASE_ADDR	0xC2200000
+#define ARM_VPB_SIZE_SHIFT	12
+
+#define SCON_BASE_ADDR		(ARM_VPB3_BASE_ADDR + (4<<ARM_VPB_SIZE_SHIFT))
+#define SCON_BASE		SCON_BASE_ADDR
+#define SCON_SYSMUX1_OFFSET	(0x010)
+#define SCON_SYSMUX1_REG	(void *)(SCON_BASE + SCON_SYSMUX1_OFFSET)
+#define SCON_GPIOA27_MUX_SHIFT	22
+#define SCON_GPIOA27_MUX_FIELD	(0xFFFFFFFF-(3<<SCON_GPIOA27_MUX_SHIFT))
+#define SCON_GPIOA27_SCL	(1<<SCON_GPIOA27_MUX_SHIFT)
+#define SCON_GPIOA28_MUX_SHIFT	24
+#define SCON_GPIOA28_MUX_FIELD	(0xFFFFFFFF-(3<<SCON_GPIOA28_MUX_SHIFT))
+#define SCON_GPIOA28_SDA	(1<<SCON_GPIOA28_MUX_SHIFT)
+
+#define CGU_BASE_ADDR		(ARM_VPB3_BASE_ADDR + (0<<ARM_VPB_SIZE_SHIFT))
+#define CGU_BASE		(CGU_BASE_ADDR)
+#define CGU_GATESC_OFFSET	(0x008)
+#define CGU_GATESC_REG		(void *)(CGU_BASE + CGU_GATESC_OFFSET)
+#define CGU_I2C1EN		0x00000020
+#define CGU_I2CEN		CGU_I2C1EN
+
+#define I2C_BASE_ADDR		(ARM_VPB1_BASE_ADDR + (1<<ARM_VPB_SIZE_SHIFT))
+#define I2C_BASE		I2C_BASE_ADDR
+#define I2C_CLKHI_OFFSET	(0x00C)
+#define I2C_CLKHI_REG		(void *)(I2C_BASE + I2C_CLKHI_OFFSET)
+#define I2C_CLKLO_OFFSET	(0x010)
+#define I2C_CLKLO_REG		(void *)(I2C_BASE + I2C_CLKLO_OFFSET)
+#define I2C_ADR_OFFSET		(0x014)
+#define I2C_ADR_REG             (void *)(I2C_BASE + I2C_ADR_OFFSET)
+#define I2C_SADDR_FIELD         0xFFFFFF80
+#define I2C_HOLDDAT_OFFSET	(0x018)
+#define I2C_HOLDDAT_REG		(void *)(I2C_BASE + I2C_HOLDDAT_OFFSET)
+#define I2C_CLKDIV_FIELD	0xFFFFFC00
+#define I2C_STS_OFFSET		(0x004)
+#define I2C_STS_REG		(void *)(I2C_BASE + I2C_STS_OFFSET)
+#define I2C_CTL_OFFSET		(0x008)
+#define I2C_CTL_REG		(void *)(I2C_BASE + I2C_CTL_OFFSET)
+#define I2C_TX_OFFSET		(0x000)
+#define I2C_TX_REG		(void *)(I2C_BASE + I2C_TX_OFFSET)
+#define I2C_RX_OFFSET		(0x000)
+#define I2C_RX_REG		(void *)(I2C_BASE + I2C_RX_OFFSET)
+
+#define I2C_TDI			0x00000001
+#define I2C_AFI			0x00000002
+#define I2C_NAI			0x00000004
+#define I2C_DRMI		0x00000008
+#define I2C_DRSI		0x00000010
+#define I2C_ACTIVE		0x00000020
+#define I2C_SCL			0x00000040
+#define I2C_SDA			0x00000080
+#define I2C_RFF			0x00000100
+#define I2C_RFE			0x00000200
+#define I2C_TFF			0x00000400
+#define I2C_TFE			0x00000800
+#define I2C_TFFS		0x00001000
+#define I2C_TFES		0x00002000
+#define I2C_MAST		0x00004000
+
+#define I2C_RESET		0x00000100
+
+#define SEND_I2C_DEVICE_ADDRESS_START_STOP(addr)	\
+			writel(((0x80 + addr) << 1) + 0x200, I2C_TX_REG);
+#define SEND_I2C_START_ADDRESS(addr)	writel((0x80 + addr) << 1, I2C_TX_REG);
+#define SEND_I2C_STOP_DATA(data)	writel(0x200 + data, I2C_TX_REG);
+#define SEND_I2C_READ_ADDRESS(addr)	\
+			writel(((0x80 + addr) << 1) + 1, I2C_TX_REG);
+#define SOFT_I2C_RESET	\
+			writel(readl(I2C_CTL_REG) | I2C_RESET, I2C_CTL_REG);
+
+int eeprom_write_enable(unsigned dev_addr, int state)
+{
+	/* nothing to be done here */
+	return 0;
+}
+
+void i2c_init(int speed, int slaveaddr)
+{
+	unsigned long timeout;
+
+	writel(readl(SCON_SYSMUX1_REG) & SCON_GPIOA27_MUX_FIELD &
+				SCON_GPIOA28_MUX_FIELD, SCON_SYSMUX1_REG);
+	writel(readl(SCON_SYSMUX1_REG) | SCON_GPIOA27_SCL | SCON_GPIOA28_SDA,
+							 SCON_SYSMUX1_REG);
+	writel(readl(CGU_GATESC_REG) | CGU_I2CEN, CGU_GATESC_REG);
+	if (speed == 400000) {
+		/*
+		 * here the registers are set in order to have a 400KHz clk
+		 * for a pclk1 of 104Mhz
+		 */
+		writel(I2C_CLKDIV_FIELD  | 84, I2C_CLKHI_REG);
+		writel(I2C_CLKDIV_FIELD  | 168, I2C_CLKLO_REG);
+		writel(42, I2C_HOLDDAT_REG);
+	} else {
+		speed = 100000;
+		/*
+		 * here the registers are set in order to have a 100KHz clk
+		 * for a pclk1 of 104Mhz
+		 */
+		writel(I2C_CLKDIV_FIELD  | 488, I2C_CLKHI_REG);
+		writel(I2C_CLKDIV_FIELD  | 544, I2C_CLKLO_REG);
+		writel(68, I2C_HOLDDAT_REG);
+	}
+	writel(slaveaddr & ~I2C_SADDR_FIELD, I2C_ADR_REG);
+	SOFT_I2C_RESET;
+	timeout = 0;
+	while ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) {
+		if (timeout > I2C_TIMEOUT)
+			break;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	debug("%s: speed: %d\n", __func__, speed);
+}
+
+
+int i2c_probe(uchar chip)
+{
+	unsigned long timeout;
+
+	SEND_I2C_DEVICE_ADDRESS_START_STOP(chip);
+	timeout = 0;
+	while ((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) {
+		if (timeout > I2C_TIMEOUT)
+			return -1;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG);
+	if ((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI)
+		return -1;
+	return 0;
+}
+
+static int i2c_read_byte(u8 chip, u16 addr, u8 *byte)
+{
+	unsigned long timeout;
+
+	timeout = 0;
+	while ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) {
+		if (timeout > I2C_TIMEOUT)
+			return -1;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	SEND_I2C_START_ADDRESS(chip);
+	/* loop if scl=1, active=0 or drmi=0 */
+	timeout = 0;
+	while (((readl(I2C_STS_REG) & I2C_SCL) == I2C_SCL) ||
+		((readl(I2C_STS_REG) & I2C_ACTIVE) != I2C_ACTIVE) ||
+		((readl(I2C_STS_REG) & I2C_DRMI) != I2C_DRMI))
+		if (timeout > I2C_TIMEOUT) {
+			return -1;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	writel((addr & 0xFF00) >> 8, I2C_TX_REG);	/* ADDRESS_MODE16 */
+	writel((addr & 0x00FF) >> 0, I2C_TX_REG);
+	SEND_I2C_READ_ADDRESS(chip);			/* Dev Sel to Read */
+	SEND_I2C_STOP_DATA(0x00);			/* dummy write */
+	timeout = 0;
+	while (((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI) ||
+		((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) ||
+		((readl(I2C_STS_REG) & I2C_SCL) != I2C_SCL) ||
+		((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) ||
+		((readl(I2C_STS_REG) & I2C_DRMI) == I2C_DRMI))
+		if (timeout > I2C_TIMEOUT) {
+			return -1;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG);
+	timeout = 0;
+	while ((readl(I2C_STS_REG) & I2C_TDI) == I2C_TDI) {
+		if (timeout > I2C_TIMEOUT)
+			return -1;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	*byte = readl(I2C_RX_REG) & 0xff;
+	return 0;
+}
+
+static int i2c_write_byte(u8 chip, u16 addr, u8 *byte)
+{
+	u8 dummy;
+	unsigned long timeout;
+
+	/* wait until data is written and eeprom back again */
+	timeout = 0;
+	dummy = 1;
+	while ((timeout < I2C_TIMEOUT) && (dummy != 0)) {
+		dummy = -i2c_probe(chip);
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	timeout = 0;
+	while ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) {
+		if (timeout > I2C_TIMEOUT)
+			return -1;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	SEND_I2C_START_ADDRESS(chip);
+	/* loop if scl=1, active=0 or drmi=0 */
+	timeout = 0;
+	while (((readl(I2C_STS_REG) & I2C_SCL) == I2C_SCL) ||
+		  ((readl(I2C_STS_REG) & I2C_ACTIVE) != I2C_ACTIVE) ||
+		  ((readl(I2C_STS_REG) & I2C_DRMI) != I2C_DRMI)) {
+		if (timeout > I2C_TIMEOUT)
+			return -2;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	writel((addr & 0xFF00) >> 8, I2C_TX_REG);	/* ADDRESS_MODE16 */
+	writel((addr & 0x00FF) >> 0, I2C_TX_REG);
+	SEND_I2C_STOP_DATA(*byte);
+	timeout = 0;
+	while (((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI) ||
+		((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) ||
+		((readl(I2C_STS_REG) & I2C_SCL) != I2C_SCL) ||
+		((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) ||
+		((readl(I2C_STS_REG) & I2C_DRMI) == I2C_DRMI)) {
+		if (timeout > I2C_TIMEOUT)
+			return -3;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG);
+	timeout = 0;
+	while ((readl(I2C_STS_REG) & I2C_TDI) == I2C_TDI) {
+		if (timeout > I2C_TIMEOUT)
+			return -4;
+		timeout++;
+		udelay(I2C_DELAY);
+	}
+	dummy = readl(I2C_RX_REG) & 0xff;
+	return 0;
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+	int ret;
+	u8 byte;
+
+	debug("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n",
+		__func__, chip, addr, alen, len);
+	while (len--) {
+		ret = i2c_read_byte(chip, addr, &byte);
+		if (ret < 0)
+			return -1;
+		*buf++ = byte;
+		addr++;
+	}
+	return 0;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+	int ret;
+
+	debug("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n",
+		__func__, chip, addr, alen, len);
+	while (len--) {
+		ret = i2c_write_byte(chip, addr++, buf++);
+		if (ret) {
+			printf("i2c_write failed chip: 0x%x addr: "
+				"0x%04x error %d\n", chip, addr, ret);
+			return -1;
+		}
+	}
+	return 0;
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
Url : http://lists.denx.de/pipermail/u-boot/attachments/20090104/4453c58e/attachment.pgp 


More information about the U-Boot mailing list