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, [email protected].
+#
+# 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 <[email protected]>
+ *
+ * (C) Copyright 2008, DSPG Technologies GmbH, Germany
+ * (C) Copyright 2007, NXP Semiconductors Germany GmbH
+ * Matthias Wenzel, <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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;
+}

Attachment: signature.asc
Description: PGP signature

_______________________________________________
U-Boot mailing list
[email protected]
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to