]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-arm
authorTom Rini <trini@ti.com>
Thu, 20 Feb 2014 17:18:59 +0000 (12:18 -0500)
committerTom Rini <trini@ti.com>
Thu, 20 Feb 2014 17:18:59 +0000 (12:18 -0500)
30 files changed:
README
arch/arc/include/asm/arch-arc700/hardware.h [deleted file]
arch/arm/dts/Makefile
arch/arm/dts/tegra124-venice2.dts [moved from board/nvidia/dts/tegra124-venice2.dts with 100% similarity]
arch/arm/include/asm/arch-spear/hardware.h
arch/blackfin/include/asm/blackfin_local.h
arch/blackfin/include/asm/clock.h
arch/blackfin/include/asm/twi.h [new file with mode: 0644]
arch/blackfin/lib/board.c
board/cm-bf548/video.c
common/cmd_otp.c
drivers/block/pata_bfin.c
drivers/bootcount/Makefile
drivers/bootcount/bootcount_i2c.c [new file with mode: 0644]
drivers/dfu/dfu_mmc.c
drivers/i2c/adi_i2c.c [new file with mode: 0644]
drivers/i2c/bfin-twi_i2c.c
drivers/i2c/designware_i2c.c
drivers/i2c/mxs_i2c.c
drivers/i2c/omap24xx_i2c.c
drivers/i2c/zynq_i2c.c
drivers/mmc/bfin_sdh.c
drivers/net/bfin_mac.c
drivers/spi/bfin_spi.c
drivers/spi/bfin_spi6xx.c
drivers/usb/musb/blackfin_usb.c
include/configs/spear-common.h
include/configs/x600.h
include/configs/zynq-common.h
include/i2c.h

diff --git a/README b/README
index d4eb0992a35795e44a69197885fdaa96f52ea6f4..423ab2cfcc118463dc57425ce3d96117270451b1 100644 (file)
--- a/README
+++ b/README
@@ -2854,6 +2854,26 @@ CBFS (Coreboot Filesystem) support
                The signing part is build into mkimage regardless of this
                option.
 
+- bootcount support:
+               CONFIG_BOOTCOUNT_LIMIT
+
+               This enables the bootcounter support, see:
+               http://www.denx.de/wiki/DULG/UBootBootCountLimit
+
+               CONFIG_AT91SAM9XE
+               enable special bootcounter support on at91sam9xe based boards.
+               CONFIG_BLACKFIN
+               enable special bootcounter support on blackfin based boards.
+               CONFIG_SOC_DA8XX
+               enable special bootcounter support on da850 based boards.
+               CONFIG_BOOTCOUNT_RAM
+               enable support for the bootcounter in RAM
+               CONFIG_BOOTCOUNT_I2C
+               enable support for the bootcounter on an i2c (like RTC) device.
+                       CONFIG_SYS_I2C_RTC_ADDR = i2c chip address
+                       CONFIG_SYS_BOOTCOUNT_ADDR = i2c addr which is used for
+                                                   the bootcounter.
+                       CONFIG_BOOTCOUNT_ALEN = address len
 
 - Show boot progress:
                CONFIG_SHOW_BOOT_PROGRESS
diff --git a/arch/arc/include/asm/arch-arc700/hardware.h b/arch/arc/include/asm/arch-arc700/hardware.h
deleted file mode 100644 (file)
index 8ec13a8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-/*
- * This file is only required to allow compilation of "designware_i2c" driver.
- * Which explicitly includes <asm/arch/hardware.h>.
- */
index 2658911ca1fb7a65b252ecbd5e28c43cd6a383c5..e2fcca567012857c3d6e84f59ece1d25aff31ec6 100644 (file)
@@ -2,7 +2,6 @@ dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \
        exynos5250-snow.dtb \
        exynos5250-smdk5250.dtb \
        exynos5420-smdk5420.dtb
-
 dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
        tegra20-medcom-wide.dtb \
        tegra20-paz00.dtb \
@@ -16,8 +15,8 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
        tegra30-beaver.dtb \
        tegra30-cardhu.dtb \
        tegra30-tec-ng.dtb \
-       tegra114-dalmore.dtb
-
+       tegra114-dalmore.dtb \
+       tegra124-venice2.dtb
 dtb-$(CONFIG_ZYNQ) += zynq-zc702.dtb \
        zynq-zc706.dtb \
        zynq-zed.dtb \
index f3afd4d06596f754e33cd75a4e2d0fd619ed3415..c6da405cc07a6fafe346999321187837ee2eaf34 100644 (file)
@@ -26,7 +26,6 @@
 #define CONFIG_SYS_NAND_ALE                    (1 << 17)
 
 #if defined(CONFIG_SPEAR600)
-#define CONFIG_SYS_I2C_BASE                    0xD0200000
 #define CONFIG_SYS_FSMC_BASE                   0xD1800000
 #define CONFIG_FSMC_NAND_BASE                  0xD2000000
 
 #define CONFIG_SPEAR_MPMCREGS                  100
 
 #elif defined(CONFIG_SPEAR300)
-#define CONFIG_SYS_I2C_BASE                    0xD0180000
 #define CONFIG_SYS_FSMC_BASE                   0x94000000
 
 #elif defined(CONFIG_SPEAR310)
-#define CONFIG_SYS_I2C_BASE                    0xD0180000
 #define CONFIG_SYS_FSMC_BASE                   0x44000000
 
 #undef CONFIG_SYS_NAND_CLE
@@ -63,7 +60,6 @@
 #define CONFIG_SYS_MACB3_BASE                  0xB1800000
 
 #elif defined(CONFIG_SPEAR320)
-#define CONFIG_SYS_I2C_BASE                    0xD0180000
 #define CONFIG_SYS_FSMC_BASE                   0x4C000000
 
 #define CONFIG_SPEAR_EMIBASE                   0x40000000
index 4d6eeab0ec126f576a00317b554b60d35ca111b2..868c82ea7db71e04a64d5965c8caedc6de64ec2b 100644 (file)
 
 # include <linux/types.h>
 
-extern u_long get_vco(void);
-extern u_long get_cclk(void);
-extern u_long get_sclk(void);
-extern u_long get_sclk0(void);
-extern u_long get_sclk1(void);
-extern u_long get_dclk(void);
-
 # define bfin_revid() (bfin_read_CHIPID() >> 28)
 
 extern int bfin_os_log_check(void);
index fc84fe43f12be1977ecd6afdcb54ce379cb9a951..59d3faa29dfac17f5cb51eecafd285cd88825d10 100644 (file)
@@ -68,10 +68,21 @@ static inline uint32_t early_get_uart_clk(void)
        return uclk;
 }
 
+extern u_long get_vco(void);
+extern u_long get_cclk(void);
+extern u_long get_sclk(void);
+
 #ifdef CGU_DIV
+extern u_long get_sclk0(void);
+extern u_long get_sclk1(void);
+extern u_long get_dclk(void);
 # define get_uart_clk get_sclk0
+# define get_i2c_clk get_sclk0
+# define get_spi_clk get_sclk0
 #else
 # define get_uart_clk get_sclk
+# define get_i2c_clk get_sclk
+# define get_spi_clk get_sclk
 #endif
 
 #endif
diff --git a/arch/blackfin/include/asm/twi.h b/arch/blackfin/include/asm/twi.h
new file mode 100644 (file)
index 0000000..922cdbd
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * i2c.c - driver for Blackfin on-chip TWI/I2C
+ *
+ * Copyright (c) 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ARCH_TWI_H
+#define __ARCH_TWI_H
+
+#include <asm/blackfin.h>
+#include <asm/mach-common/bits/twi.h>
+
+#endif
index facbc7a563f34eb8cb9ebccb5626d7c033a82665..62342014a4703570e2d190d1219e5942218ff3e7 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/cplb.h>
 #include <asm/mach-common/bits/mpu.h>
+#include <asm/clock.h>
 #include <kgdb.h>
 
 #ifdef CONFIG_CMD_NAND
index a43413e976fc242081f0ff93443ce54932410d82..c35d28507088d429b7a54826965869c5393c78f4 100644 (file)
@@ -11,6 +11,7 @@
 #include <config.h>
 #include <malloc.h>
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/gpio.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/dma.h>
index 6f933355176296ac2541d0b45960dfbef87bb27d..67808aa377ef15cdf3059bae08e6bfe8592ca886 100644 (file)
@@ -18,6 +18,7 @@
 #include <command.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/mach-common/bits/otp.h>
 
 static const char *otp_strerror(uint32_t err)
index 27ecaf4f9edad9b87b69e2ad990e2ef2cf014592..b7fd1cd634486639647bec5c9988001ca17993c1 100644 (file)
@@ -12,6 +12,7 @@
 #include <command.h>
 #include <config.h>
 #include <asm/byteorder.h>
+#include <asm/clock.h>
 #include <asm/io.h>
 #include <asm/errno.h>
 #include <asm/portmux.h>
index bed6971aa55680dbea031f4ed60f3c453523687b..6f1c419c7a708e9976aa7cdc49dff6dffddf763d 100644 (file)
@@ -9,3 +9,4 @@ obj-$(CONFIG_SOC_DA8XX)         += bootcount_davinci.o
 obj-$(CONFIG_BOOTCOUNT_AM33XX) += bootcount_davinci.o
 obj-$(CONFIG_BOOTCOUNT_RAM)    += bootcount_ram.o
 obj-$(CONFIG_BOOTCOUNT_ENV)    += bootcount_env.o
+obj-$(CONFIG_BOOTCOUNT_I2C)    += bootcount_i2c.o
diff --git a/drivers/bootcount/bootcount_i2c.c b/drivers/bootcount/bootcount_i2c.c
new file mode 100644 (file)
index 0000000..e27b168
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 2013
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <bootcount.h>
+#include <linux/compiler.h>
+#include <i2c.h>
+
+#define BC_MAGIC       0xbc
+
+void bootcount_store(ulong a)
+{
+       unsigned char buf[3];
+       int ret;
+
+       buf[0] = BC_MAGIC;
+       buf[1] = (a & 0xff);
+       ret = i2c_write(CONFIG_SYS_I2C_RTC_ADDR, CONFIG_SYS_BOOTCOUNT_ADDR,
+                 CONFIG_BOOTCOUNT_ALEN, buf, 2);
+       if (ret != 0)
+               puts("Error writing bootcount\n");
+}
+
+ulong bootcount_load(void)
+{
+       unsigned char buf[3];
+       int ret;
+
+       ret = i2c_read(CONFIG_SYS_I2C_RTC_ADDR, CONFIG_SYS_BOOTCOUNT_ADDR,
+                      CONFIG_BOOTCOUNT_ALEN, buf, 2);
+       if (ret != 0) {
+               puts("Error loading bootcount\n");
+               return 0;
+       }
+       if (buf[0] == BC_MAGIC)
+               return buf[1];
+
+       bootcount_store(0);
+
+       return 0;
+}
index f942758696e326843368847d0ef947b8be41d32b..0816f46bad8ebcd6350319f98be8dbeb6ed7f046 100644 (file)
@@ -73,16 +73,12 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
                        op == DFU_OP_READ ? "load" : "write",
                        dfu->data.mmc.dev, dfu->data.mmc.part,
                        (unsigned int) buf, dfu->name);
-               if (op == DFU_OP_WRITE)
-                       sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len);
                break;
        case DFU_FS_EXT4:
                sprintf(cmd_buf, "ext4%s mmc %d:%d 0x%x /%s",
                        op == DFU_OP_READ ? "load" : "write",
                        dfu->data.mmc.dev, dfu->data.mmc.part,
                        (unsigned int) buf, dfu->name);
-               if (op == DFU_OP_WRITE)
-                       sprintf(cmd_buf + strlen(cmd_buf), " %ld", *len);
                break;
        default:
                printf("%s: Layout (%s) not (yet) supported!\n", __func__,
@@ -90,6 +86,9 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
                return -1;
        }
 
+       if (op == DFU_OP_WRITE)
+               sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len);
+
        debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
 
        ret = run_command(cmd_buf, 0);
diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c
new file mode 100644 (file)
index 0000000..675f417
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * i2c.c - driver for ADI TWI/I2C
+ *
+ * Copyright (c) 2006-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <asm/clock.h>
+#include <asm/twi.h>
+#include <asm/io.h>
+
+/* Every register is 32bit aligned, but only 16bits in size */
+#define ureg(name) u16 name; u16 __pad_##name;
+struct twi_regs {
+       ureg(clkdiv);
+       ureg(control);
+       ureg(slave_ctl);
+       ureg(slave_stat);
+       ureg(slave_addr);
+       ureg(master_ctl);
+       ureg(master_stat);
+       ureg(master_addr);
+       ureg(int_stat);
+       ureg(int_mask);
+       ureg(fifo_ctl);
+       ureg(fifo_stat);
+       char __pad[0x50];
+       ureg(xmt_data8);
+       ureg(xmt_data16);
+       ureg(rcv_data8);
+       ureg(rcv_data16);
+};
+#undef ureg
+
+/* U-Boot I2C framework allows only one active device at a time.  */
+#ifdef TWI_CLKDIV
+#define TWI0_CLKDIV TWI_CLKDIV
+#endif
+static struct twi_regs *twi = (void *)TWI0_CLKDIV;
+
+#ifdef DEBUG
+# define dmemset(s, c, n) memset(s, c, n)
+#else
+# define dmemset(s, c, n)
+#endif
+#define debugi(fmt, args...) \
+       debug( \
+               "MSTAT:0x%03x FSTAT:0x%x ISTAT:0x%02x\t%-20s:%-3i: " fmt "\n", \
+               twi->master_stat, twi->fifo_stat, twi->int_stat, \
+               __func__, __LINE__, ## args)
+
+#ifdef CONFIG_TWICLK_KHZ
+# error do not define CONFIG_TWICLK_KHZ ... use CONFIG_SYS_I2C_SPEED
+#endif
+
+/*
+ * The way speed is changed into duty often results in integer truncation
+ * with 50% duty, so we'll force rounding up to the next duty by adding 1
+ * to the max.  In practice this will get us a speed of something like
+ * 385 KHz.  The other limit is easy to handle as it is only 8 bits.
+ */
+#define I2C_SPEED_MAX             400000
+#define I2C_SPEED_TO_DUTY(speed)  (5000000 / (speed))
+#define I2C_DUTY_MAX              (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1)
+#define I2C_DUTY_MIN              0xff /* 8 bit limited */
+#define SYS_I2C_DUTY              I2C_SPEED_TO_DUTY(CONFIG_SYS_I2C_SPEED)
+/* Note: duty is inverse of speed, so the comparisons below are correct */
+#if SYS_I2C_DUTY < I2C_DUTY_MAX || SYS_I2C_DUTY > I2C_DUTY_MIN
+# error "The Blackfin I2C hardware can only operate 20KHz - 400KHz"
+#endif
+
+/* All transfers are described by this data structure */
+struct i2c_msg {
+       u8 flags;
+#define I2C_M_COMBO            0x4
+#define I2C_M_STOP             0x2
+#define I2C_M_READ             0x1
+       int len;                /* msg length */
+       u8 *buf;                /* pointer to msg data */
+       int alen;               /* addr length */
+       u8 *abuf;               /* addr buffer */
+};
+
+/* Allow msec timeout per ~byte transfer */
+#define I2C_TIMEOUT 10
+
+/**
+ * wait_for_completion - manage the actual i2c transfer
+ *     @msg: the i2c msg
+ */
+static int wait_for_completion(struct i2c_msg *msg)
+{
+       u16 int_stat, ctl;
+       ulong timebase = get_timer(0);
+
+       do {
+               int_stat = readw(&twi->int_stat);
+
+               if (int_stat & XMTSERV) {
+                       debugi("processing XMTSERV");
+                       writew(XMTSERV, &twi->int_stat);
+                       if (msg->alen) {
+                               writew(*(msg->abuf++), &twi->xmt_data8);
+                               --msg->alen;
+                       } else if (!(msg->flags & I2C_M_COMBO) && msg->len) {
+                               writew(*(msg->buf++), &twi->xmt_data8);
+                               --msg->len;
+                       } else {
+                               ctl = readw(&twi->master_ctl);
+                               if (msg->flags & I2C_M_COMBO)
+                                       writew(ctl | RSTART | MDIR,
+                                                       &twi->master_ctl);
+                               else
+                                       writew(ctl | STOP, &twi->master_ctl);
+                       }
+               }
+               if (int_stat & RCVSERV) {
+                       debugi("processing RCVSERV");
+                       writew(RCVSERV, &twi->int_stat);
+                       if (msg->len) {
+                               *(msg->buf++) = readw(&twi->rcv_data8);
+                               --msg->len;
+                       } else if (msg->flags & I2C_M_STOP) {
+                               ctl = readw(&twi->master_ctl);
+                               writew(ctl | STOP, &twi->master_ctl);
+                       }
+               }
+               if (int_stat & MERR) {
+                       debugi("processing MERR");
+                       writew(MERR, &twi->int_stat);
+                       return msg->len;
+               }
+               if (int_stat & MCOMP) {
+                       debugi("processing MCOMP");
+                       writew(MCOMP, &twi->int_stat);
+                       if (msg->flags & I2C_M_COMBO && msg->len) {
+                               ctl = readw(&twi->master_ctl);
+                               ctl = (ctl & ~RSTART) |
+                                       (min(msg->len, 0xff) << 6) | MEN | MDIR;
+                               writew(ctl, &twi->master_ctl);
+                       } else
+                               break;
+               }
+
+               /* If we were able to do something, reset timeout */
+               if (int_stat)
+                       timebase = get_timer(0);
+
+       } while (get_timer(timebase) < I2C_TIMEOUT);
+
+       return msg->len;
+}
+
+/**
+ * i2c_transfer - setup an i2c transfer
+ *     @return: 0 if things worked, non-0 if things failed
+ *
+ *     Here we just get the i2c stuff all prepped and ready, and then tail off
+ *     into wait_for_completion() for all the bits to go.
+ */
+static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer,
+                       int len, u8 flags)
+{
+       int ret;
+       u16 ctl;
+       uchar addr_buffer[] = {
+               (addr >>  0),
+               (addr >>  8),
+               (addr >> 16),
+       };
+       struct i2c_msg msg = {
+               .flags = flags | (len >= 0xff ? I2C_M_STOP : 0),
+               .buf   = buffer,
+               .len   = len,
+               .abuf  = addr_buffer,
+               .alen  = alen,
+       };
+
+       dmemset(buffer, 0xff, len);
+       debugi("chip=0x%x addr=0x%02x alen=%i buf[0]=0x%02x len=%i ",
+               chip, addr, alen, buffer[0], len);
+       debugi("flags=0x%02x[%s] ", flags,
+               (flags & I2C_M_READ ? "rd" : "wr"));
+
+       /* wait for things to settle */
+       while (readw(&twi->master_stat) & BUSBUSY)
+               if (ctrlc())
+                       return 1;
+
+       /* Set Transmit device address */
+       writew(chip, &twi->master_addr);
+
+       /* Clear the FIFO before starting things */
+       writew(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl);
+       writew(0, &twi->fifo_ctl);
+
+       /* prime the pump */
+       if (msg.alen) {
+               len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len;
+               debugi("first byte=0x%02x", *msg.abuf);
+               writew(*(msg.abuf++), &twi->xmt_data8);
+               --msg.alen;
+       } else if (!(msg.flags & I2C_M_READ) && msg.len) {
+               debugi("first byte=0x%02x", *msg.buf);
+               writew(*(msg.buf++), &twi->xmt_data8);
+               --msg.len;
+       }
+
+       /* clear int stat */
+       writew(-1, &twi->master_stat);
+       writew(-1, &twi->int_stat);
+       writew(0, &twi->int_mask);
+
+       /* Master enable */
+       ctl = readw(&twi->master_ctl);
+       ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN |
+               ((msg.flags & I2C_M_READ) ? MDIR : 0);
+       writew(ctl, &twi->master_ctl);
+
+       /* process the rest */
+       ret = wait_for_completion(&msg);
+       debugi("ret=%d", ret);
+
+       if (ret) {
+               ctl = readw(&twi->master_ctl) & ~MEN;
+               writew(ctl, &twi->master_ctl);
+               ctl = readw(&twi->control) & ~TWI_ENA;
+               writew(ctl, &twi->control);
+               ctl = readw(&twi->control) | TWI_ENA;
+               writew(ctl, &twi->control);
+       }
+
+       return ret;
+}
+
+/**
+ * i2c_set_bus_speed - set i2c bus speed
+ *     @speed: bus speed (in HZ)
+ */
+int i2c_set_bus_speed(unsigned int speed)
+{
+       u16 clkdiv = I2C_SPEED_TO_DUTY(speed);
+
+       /* Set TWI interface clock */
+       if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN)
+               return -1;
+       clkdiv = (clkdiv << 8) | (clkdiv & 0xff);
+       writew(clkdiv, &twi->clkdiv);
+
+       /* Don't turn it on */
+       writew(speed > 100000 ? FAST : 0, &twi->master_ctl);
+
+       return 0;
+}
+
+/**
+ * i2c_get_bus_speed - get i2c bus speed
+ *     @speed: bus speed (in HZ)
+ */
+unsigned int i2c_get_bus_speed(void)
+{
+       u16 clkdiv = readw(&twi->clkdiv) & 0xff;
+       /* 10 MHz / (2 * CLKDIV) -> 5 MHz / CLKDIV */
+       return 5000000 / clkdiv;
+}
+
+/**
+ * i2c_init - initialize the i2c bus
+ *     @speed: bus speed (in HZ)
+ *     @slaveaddr: address of device in slave mode (0 - not slave)
+ *
+ *     Slave mode isn't actually implemented.  It'll stay that way until
+ *     we get a real request for it.
+ */
+void i2c_init(int speed, int slaveaddr)
+{
+       u16 prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F;
+
+       /* Set TWI internal clock as 10MHz */
+       writew(prescale, &twi->control);
+
+       /* Set TWI interface clock as specified */
+       i2c_set_bus_speed(speed);
+
+       /* Enable it */
+       writew(TWI_ENA | prescale, &twi->control);
+
+       debugi("CONTROL:0x%04x CLKDIV:0x%04x", readw(&twi->control),
+               readw(&twi->clkdiv));
+
+#if CONFIG_SYS_I2C_SLAVE
+# error I2C slave support not tested/supported
+#endif
+}
+
+/**
+ * i2c_probe - test if a chip exists at a given i2c address
+ *     @chip: i2c chip addr to search for
+ *     @return: 0 if found, non-0 if not found
+ */
+int i2c_probe(uchar chip)
+{
+       u8 byte;
+       return i2c_read(chip, 0, 0, &byte, 1);
+}
+
+/**
+ * i2c_read - read data from an i2c device
+ *     @chip: i2c chip addr
+ *     @addr: memory (register) address in the chip
+ *     @alen: byte size of address
+ *     @buffer: buffer to store data read from chip
+ *     @len: how many bytes to read
+ *     @return: 0 on success, non-0 on failure
+ */
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+       return i2c_transfer(chip, addr, alen, buffer,
+                       len, (alen ? I2C_M_COMBO : I2C_M_READ));
+}
+
+/**
+ * i2c_write - write data to an i2c device
+ *     @chip: i2c chip addr
+ *     @addr: memory (register) address in the chip
+ *     @alen: byte size of address
+ *     @buffer: buffer holding data to write to chip
+ *     @len: how many bytes to write
+ *     @return: 0 on success, non-0 on failure
+ */
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+       return i2c_transfer(chip, addr, alen, buffer, len, 0);
+}
+
+/**
+ * i2c_set_bus_num - change active I2C bus
+ *     @bus: bus index, zero based
+ *     @returns: 0 on success, non-0 on failure
+ */
+int i2c_set_bus_num(unsigned int bus)
+{
+       switch (bus) {
+#if CONFIG_SYS_MAX_I2C_BUS > 0
+       case 0:
+               twi = (void *)TWI0_CLKDIV;
+               return 0;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 1
+       case 1:
+               twi = (void *)TWI1_CLKDIV;
+               return 0;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 2
+       case 2:
+               twi = (void *)TWI2_CLKDIV;
+               return 0;
+#endif
+       default: return -1;
+       }
+}
+
+/**
+ * i2c_get_bus_num - returns index of active I2C bus
+ */
+unsigned int i2c_get_bus_num(void)
+{
+       switch ((unsigned long)twi) {
+#if CONFIG_SYS_MAX_I2C_BUS > 0
+       case TWI0_CLKDIV:
+               return 0;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 1
+       case TWI1_CLKDIV:
+               return 1;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 2
+       case TWI2_CLKDIV:
+               return 2;
+#endif
+       default: return -1;
+       }
+}
index b3a04d32074a2242d5f647e592083f47b09d865a..cfab064dfad600b400f96b4863c0ab2100a14881 100644 (file)
@@ -10,6 +10,7 @@
 #include <i2c.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/mach-common/bits/twi.h>
 
 /* Every register is 32bit aligned, but only 16bits in size */
@@ -274,7 +275,7 @@ unsigned int i2c_get_bus_speed(void)
  */
 void i2c_init(int speed, int slaveaddr)
 {
-       uint8_t prescale = ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F;
+       uint8_t prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F;
 
        /* Set TWI internal clock as 10MHz */
        twi->control = prescale;
index 9ed929521a8944dc870fc2eff546507632b6e86a..c891ebd39e243ebc5540e7db6291ed88f7e84678 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <common.h>
 #include <asm/io.h>
-#include <asm/arch/hardware.h>
 #include "designware_i2c.h"
 
 #ifdef CONFIG_I2C_MULTI_BUS
@@ -197,35 +196,18 @@ static int i2c_wait_for_bb(void)
        return 0;
 }
 
-/* check parameters for i2c_read and i2c_write */
-static int check_params(uint addr, int alen, uchar *buffer, int len)
-{
-       if (buffer == NULL) {
-               printf("Buffer is invalid\n");
-               return 1;
-       }
-
-       if (alen > 1) {
-               printf("addr len %d not supported\n", alen);
-               return 1;
-       }
-
-       if (addr + len > 256) {
-               printf("address out of range\n");
-               return 1;
-       }
-
-       return 0;
-}
-
-static int i2c_xfer_init(uchar chip, uint addr)
+static int i2c_xfer_init(uchar chip, uint addr, int alen)
 {
        if (i2c_wait_for_bb())
                return 1;
 
        i2c_setaddress(chip);
-       writel(addr, &i2c_regs_p->ic_cmd_data);
-
+       while (alen) {
+               alen--;
+               /* high byte address going out first */
+               writel((addr >> (alen * 8)) & 0xff,
+                      &i2c_regs_p->ic_cmd_data);
+       }
        return 0;
 }
 
@@ -285,10 +267,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
              addr);
 #endif
 
-       if (check_params(addr, alen, buffer, len))
-               return 1;
-
-       if (i2c_xfer_init(chip, addr))
+       if (i2c_xfer_init(chip, addr, alen))
                return 1;
 
        start_time_rx = get_timer(0);
@@ -345,10 +324,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
              addr);
 #endif
 
-       if (check_params(addr, alen, buffer, len))
-               return 1;
-
-       if (i2c_xfer_init(chip, addr))
+       if (i2c_xfer_init(chip, addr, alen))
                return 1;
 
        start_time_tx = get_timer(0);
index a298c95e144ae3e35de1b0e2136929b793a282ad..de3b19402b4af1c2f8a97283a77a0d92d034b0ed 100644 (file)
@@ -64,16 +64,17 @@ static void mxs_i2c_setup_read(uint8_t chip, int len)
        writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
 }
 
-static void mxs_i2c_write(uchar chip, uint addr, int alen,
+static int mxs_i2c_write(uchar chip, uint addr, int alen,
                        uchar *buf, int blen, int stop)
 {
        struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
-       uint32_t data;
+       uint32_t data, tmp;
        int i, remain, off;
+       int timeout = MXS_I2C_MAX_TIMEOUT;
 
        if ((alen > 4) || (alen == 0)) {
                debug("MXS I2C: Invalid address length\n");
-               return;
+               return -EINVAL;
        }
 
        if (stop)
@@ -106,6 +107,19 @@ static void mxs_i2c_write(uchar chip, uint addr, int alen,
                writel(data >> remain, &i2c_regs->hw_i2c_data);
 
        writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
+
+       while (--timeout) {
+               tmp = readl(&i2c_regs->hw_i2c_queuestat);
+               if (tmp & I2C_QUEUESTAT_WR_QUEUE_EMPTY)
+                       break;
+       }
+
+       if (!timeout) {
+               debug("MXS I2C: Failed transmitting data!\n");
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 static int mxs_i2c_wait_for_ack(void)
@@ -154,7 +168,12 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
        int ret;
        int i;
 
-       mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
+       ret = mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
+       if (ret) {
+               debug("MXS I2C: Failed writing address\n");
+               return ret;
+       }
+
        ret = mxs_i2c_wait_for_ack();
        if (ret) {
                debug("MXS I2C: Failed writing address\n");
@@ -193,7 +212,12 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 {
        int ret;
-       mxs_i2c_write(chip, addr, alen, buffer, len, 1);
+       ret = mxs_i2c_write(chip, addr, alen, buffer, len, 1);
+       if (ret) {
+               debug("MXS I2C: Failed writing address\n");
+               return ret;
+       }
+
        ret = mxs_i2c_wait_for_ack();
        if (ret)
                debug("MXS I2C: Failed writing address\n");
@@ -204,8 +228,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 int i2c_probe(uchar chip)
 {
        int ret;
-       mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
-       ret = mxs_i2c_wait_for_ack();
+       ret = mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
+       if (!ret)
+               ret = mxs_i2c_wait_for_ack();
        mxs_i2c_reset();
        return ret;
 }
index c7840049b11c707d1eaa9c90899f3d3120d22e2d..a39b5917ecd89f0bb11f048e4cde9d721250e574 100644 (file)
  * - Status functions now read irqstatus_raw as per TRM guidelines
  *   (except for OMAP243X and OMAP34XX).
  * - Driver now supports up to I2C5 (OMAP5).
+ *
+ * Copyright (c) 2014 Hannes Petermaier <oe5hpm@oevsv.at>, B&R
+ * - Added support for set_speed
+ *
  */
 
 #include <common.h>
@@ -53,43 +57,66 @@ static int wait_for_bb(struct i2c_adapter *adap);
 static struct i2c *omap24_get_base(struct i2c_adapter *adap);
 static u16 wait_for_event(struct i2c_adapter *adap);
 static void flush_fifo(struct i2c_adapter *adap);
-
-static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
 {
-       struct i2c *i2c_base = omap24_get_base(adap);
-       int psc, fsscll, fssclh;
-       int hsscll = 0, hssclh = 0;
-       u32 scll, sclh;
-       int timeout = I2C_TIMEOUT;
+       unsigned int sampleclk, prescaler;
+       int fsscll, fssclh;
 
-       /* Only handle standard, fast and high speeds */
-       if ((speed != OMAP_I2C_STANDARD) &&
-           (speed != OMAP_I2C_FAST_MODE) &&
-           (speed != OMAP_I2C_HIGH_SPEED)) {
-               printf("Error : I2C unsupported speed %d\n", speed);
-               return;
-       }
+       speed <<= 1;
+       prescaler = 0;
+       /*
+        * some divisors may cause a precission loss, but shouldn't
+        * be a big thing, because i2c_clk is then allready very slow.
+        */
+       while (prescaler <= 0xFF) {
+               sampleclk = I2C_IP_CLK / (prescaler+1);
 
-       psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
-       psc -= 1;
-       if (psc < I2C_PSC_MIN) {
-               printf("Error : I2C unsupported prescalar %d\n", psc);
-               return;
+               fsscll = sampleclk / speed;
+               fssclh = fsscll;
+               fsscll -= I2C_FASTSPEED_SCLL_TRIM;
+               fssclh -= I2C_FASTSPEED_SCLH_TRIM;
+
+               if (((fsscll > 0) && (fssclh > 0)) &&
+                   ((fsscll <= (255-I2C_FASTSPEED_SCLL_TRIM)) &&
+                   (fssclh <= (255-I2C_FASTSPEED_SCLH_TRIM)))) {
+                       if (pscl)
+                               *pscl = fsscll;
+                       if (psch)
+                               *psch = fssclh;
+
+                       return prescaler;
+               }
+               prescaler++;
        }
+       return -1;
+}
+static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
+{
+       struct i2c *i2c_base = omap24_get_base(adap);
+       int psc, fsscll = 0, fssclh = 0;
+       int hsscll = 0, hssclh = 0;
+       u32 scll = 0, sclh = 0;
 
-       if (speed == OMAP_I2C_HIGH_SPEED) {
+       if (speed >= OMAP_I2C_HIGH_SPEED) {
                /* High speed */
+               psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
+               psc -= 1;
+               if (psc < I2C_PSC_MIN) {
+                       printf("Error : I2C unsupported prescaler %d\n", psc);
+                       return -1;
+               }
 
                /* For first phase of HS mode */
-               fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK /
-                       (2 * OMAP_I2C_FAST_MODE);
+               fsscll = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
+
+               fssclh = fsscll;
 
                fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
                fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
                if (((fsscll < 0) || (fssclh < 0)) ||
                    ((fsscll > 255) || (fssclh > 255))) {
                        puts("Error : I2C initializing first phase clock\n");
-                       return;
+                       return -1;
                }
 
                /* For second phase of HS mode */
@@ -100,7 +127,7 @@ static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
                if (((fsscll < 0) || (fssclh < 0)) ||
                    ((fsscll > 255) || (fssclh > 255))) {
                        puts("Error : I2C initializing second phase clock\n");
-                       return;
+                       return -1;
                }
 
                scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll;
@@ -108,20 +135,29 @@ static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
 
        } else {
                /* Standard and fast speed */
-               fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
-
-               fsscll -= I2C_FASTSPEED_SCLL_TRIM;
-               fssclh -= I2C_FASTSPEED_SCLH_TRIM;
-               if (((fsscll < 0) || (fssclh < 0)) ||
-                   ((fsscll > 255) || (fssclh > 255))) {
+               psc = omap24_i2c_findpsc(&scll, &sclh, speed);
+               if (0 > psc) {
                        puts("Error : I2C initializing clock\n");
-                       return;
+                       return -1;
                }
-
-               scll = (unsigned int)fsscll;
-               sclh = (unsigned int)fssclh;
        }
 
+       adap->speed     = speed;
+       adap->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */
+       writew(0, &i2c_base->con);
+       writew(psc, &i2c_base->psc);
+       writew(scll, &i2c_base->scll);
+       writew(sclh, &i2c_base->sclh);
+       writew(I2C_CON_EN, &i2c_base->con);
+       writew(0xFFFF, &i2c_base->stat);        /* clear all pending status */
+
+       return 0;
+}
+static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+{
+       struct i2c *i2c_base = omap24_get_base(adap);
+       int timeout = I2C_TIMEOUT;
+
        if (readw(&i2c_base->con) & I2C_CON_EN) {
                writew(0, &i2c_base->con);
                udelay(50000);
@@ -139,14 +175,14 @@ static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
                udelay(1000);
        }
 
-       writew(0, &i2c_base->con);
-       writew(psc, &i2c_base->psc);
-       writew(scll, &i2c_base->scll);
-       writew(sclh, &i2c_base->sclh);
+       if (0 != omap24_i2c_setspeed(adap, speed)) {
+               printf("ERROR: failed to setup I2C bus-speed!\n");
+               return;
+       }
 
        /* own address */
        writew(slaveadd, &i2c_base->oa);
-       writew(I2C_CON_EN, &i2c_base->con);
+
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
        /*
         * Have to enable interrupts for OMAP2/3, these IPs don't have
@@ -165,7 +201,8 @@ static void flush_fifo(struct i2c_adapter *adap)
        struct i2c *i2c_base = omap24_get_base(adap);
        u16 stat;
 
-       /* note: if you try and read data when its not there or ready
+       /*
+        * note: if you try and read data when its not there or ready
         * you get a bus error
         */
        while (1) {
@@ -220,8 +257,8 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
 
        /* Check for ACK (!NAK) */
        if (!(status & I2C_STAT_NACK)) {
-               res = 0;                        /* Device found */
-               udelay(I2C_WAIT);               /* Required by AM335X in SPL */
+               res = 0;                                /* Device found */
+               udelay(adap->waitdelay);/* Required by AM335X in SPL */
                /* Abort transfer (force idle state) */
                writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
                udelay(1000);
@@ -307,7 +344,7 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
                                       adap->hwadapnr, status);
                                goto rd_exit;
                        }
-                       if (status == 0 || status & I2C_STAT_NACK) {
+                       if (status == 0 || (status & I2C_STAT_NACK)) {
                                i2c_error = 1;
                                printf("i2c_read: error waiting for addr ACK (status=0x%x)\n",
                                       status);
@@ -351,7 +388,7 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
                               adap->hwadapnr, status);
                        goto rd_exit;
                }
-               if (status == 0 || status & I2C_STAT_NACK) {
+               if (status == 0 || (status & I2C_STAT_NACK)) {
                        i2c_error = 1;
                        goto rd_exit;
                }
@@ -379,6 +416,7 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
        int i;
        u16 status;
        int i2c_error = 0;
+       int timeout = I2C_TIMEOUT;
 
        if (alen < 0) {
                puts("I2C write: addr len < 0\n");
@@ -428,7 +466,7 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
                               adap->hwadapnr, status);
                        goto wr_exit;
                }
-               if (status == 0 || status & I2C_STAT_NACK) {
+               if (status == 0 || (status & I2C_STAT_NACK)) {
                        i2c_error = 1;
                        printf("i2c_write: error waiting for addr ACK (status=0x%x)\n",
                               status);
@@ -448,7 +486,7 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
        /* Address phase is over, now write data */
        for (i = 0; i < len; i++) {
                status = wait_for_event(adap);
-               if (status == 0 || status & I2C_STAT_NACK) {
+               if (status == 0 || (status & I2C_STAT_NACK)) {
                        i2c_error = 1;
                        printf("i2c_write: error waiting for data ACK (status=0x%x)\n",
                               status);
@@ -464,6 +502,15 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
                        goto wr_exit;
                }
        }
+       /*
+        * poll ARDY bit for making sure that last byte really has been
+        * transferred on the bus.
+        */
+       do {
+               status = wait_for_event(adap);
+       } while (!(status & I2C_STAT_ARDY) && timeout--);
+       if (timeout <= 0)
+               printf("i2c_write: timed out writig last byte!\n");
 
 wr_exit:
        flush_fifo(adap);
@@ -490,7 +537,7 @@ static int wait_for_bb(struct i2c_adapter *adap)
                I2C_STAT_BB) && timeout--) {
 #endif
                writew(stat, &i2c_base->stat);
-               udelay(I2C_WAIT);
+               udelay(adap->waitdelay);
        }
 
        if (timeout <= 0) {
@@ -513,7 +560,7 @@ static u16 wait_for_event(struct i2c_adapter *adap)
        int timeout = I2C_TIMEOUT;
 
        do {
-               udelay(I2C_WAIT);
+               udelay(adap->waitdelay);
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
                status = readw(&i2c_base->stat);
 #else
@@ -580,12 +627,12 @@ static struct i2c *omap24_get_base(struct i2c_adapter *adap)
 #endif
 
 U_BOOT_I2C_ADAP_COMPLETE(omap24_0, omap24_i2c_init, omap24_i2c_probe,
-                        omap24_i2c_read, omap24_i2c_write, NULL,
+                        omap24_i2c_read, omap24_i2c_write, omap24_i2c_setspeed,
                         CONFIG_SYS_OMAP24_I2C_SPEED,
                         CONFIG_SYS_OMAP24_I2C_SLAVE,
                         0)
 U_BOOT_I2C_ADAP_COMPLETE(omap24_1, omap24_i2c_init, omap24_i2c_probe,
-                        omap24_i2c_read, omap24_i2c_write, NULL,
+                        omap24_i2c_read, omap24_i2c_write, omap24_i2c_setspeed,
                         CONFIG_SYS_OMAP24_I2C_SPEED1,
                         CONFIG_SYS_OMAP24_I2C_SLAVE1,
                         1)
index 70a9aeafd531124c70c0f45afdf98541872fb1e2..f1f65131a2a93166afffcb053e4d607029180a08 100644 (file)
@@ -64,19 +64,21 @@ struct zynq_i2c_registers {
 #define ZYNQ_I2C_FIFO_DEPTH            16
 #define ZYNQ_I2C_TRANSFERT_SIZE_MAX    255 /* Controller transfer limit */
 
-#if defined(CONFIG_ZYNQ_I2C0)
-# define ZYNQ_I2C_BASE ZYNQ_I2C_BASEADDR0
-#else
-# define ZYNQ_I2C_BASE ZYNQ_I2C_BASEADDR1
-#endif
-
-static struct zynq_i2c_registers *zynq_i2c =
-       (struct zynq_i2c_registers *)ZYNQ_I2C_BASE;
+static struct zynq_i2c_registers *i2c_select(struct i2c_adapter *adap)
+{
+       return adap->hwadapnr ?
+               /* Zynq PS I2C1 */
+               (struct zynq_i2c_registers *)ZYNQ_I2C_BASEADDR1 :
+               /* Zynq PS I2C0 */
+               (struct zynq_i2c_registers *)ZYNQ_I2C_BASEADDR0;
+}
 
 /* I2C init called by cmd_i2c when doing 'i2c reset'. */
 static void zynq_i2c_init(struct i2c_adapter *adap, int requested_speed,
                          int slaveadd)
 {
+       struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
+
        /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */
        writel((16 << ZYNQ_I2C_CONTROL_DIV_B_SHIFT) |
                (2 << ZYNQ_I2C_CONTROL_DIV_A_SHIFT), &zynq_i2c->control);
@@ -87,7 +89,7 @@ static void zynq_i2c_init(struct i2c_adapter *adap, int requested_speed,
 }
 
 #ifdef DEBUG
-static void zynq_i2c_debug_status(void)
+static void zynq_i2c_debug_status(struct zynq_i2c_registers *zynq_i2c)
 {
        int int_status;
        int status;
@@ -129,7 +131,7 @@ static void zynq_i2c_debug_status(void)
 #endif
 
 /* Wait for an interrupt */
-static u32 zynq_i2c_wait(u32 mask)
+static u32 zynq_i2c_wait(struct zynq_i2c_registers *zynq_i2c, u32 mask)
 {
        int timeout, int_status;
 
@@ -140,7 +142,7 @@ static u32 zynq_i2c_wait(u32 mask)
                        break;
        }
 #ifdef DEBUG
-       zynq_i2c_debug_status();
+       zynq_i2c_debug_status(zynq_i2c));
 #endif
        /* Clear interrupt status flags */
        writel(int_status & mask, &zynq_i2c->interrupt_status);
@@ -154,6 +156,8 @@ static u32 zynq_i2c_wait(u32 mask)
  */
 static int zynq_i2c_probe(struct i2c_adapter *adap, u8 dev)
 {
+       struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
+
        /* Attempt to read a byte */
        setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
                ZYNQ_I2C_CONTROL_RW);
@@ -162,7 +166,7 @@ static int zynq_i2c_probe(struct i2c_adapter *adap, u8 dev)
        writel(dev, &zynq_i2c->address);
        writel(1, &zynq_i2c->transfer_size);
 
-       return (zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP |
+       return (zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP |
                ZYNQ_I2C_INTERRUPT_NACK) &
                ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT;
 }
@@ -177,6 +181,7 @@ static int zynq_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
        u32 status;
        u32 i = 0;
        u8 *cur_data = data;
+       struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
 
        /* Check the hardware can handle the requested bytes */
        if ((length < 0) || (length > ZYNQ_I2C_TRANSFERT_SIZE_MAX))
@@ -189,20 +194,22 @@ static int zynq_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
         * Temporarily disable restart (by clearing hold)
         * It doesn't seem to work.
         */
-       clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW |
-               ZYNQ_I2C_CONTROL_HOLD);
+       clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
        writel(0xFF, &zynq_i2c->interrupt_status);
-       while (alen--)
-               writel(addr >> (8*alen), &zynq_i2c->data);
-       writel(dev, &zynq_i2c->address);
+       if (alen) {
+               clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW);
+               writel(dev, &zynq_i2c->address);
+               while (alen--)
+                       writel(addr >> (8 * alen), &zynq_i2c->data);
 
-       /* Wait for the address to be sent */
-       if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) {
-               /* Release the bus */
-               clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
-               return -ETIMEDOUT;
+               /* Wait for the address to be sent */
+               if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
+                       /* Release the bus */
+                       clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
+                       return -ETIMEDOUT;
+               }
+               debug("Device acked address\n");
        }
-       debug("Device acked address\n");
 
        setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
                ZYNQ_I2C_CONTROL_RW);
@@ -212,7 +219,7 @@ static int zynq_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
 
        /* Wait for data */
        do {
-               status = zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP |
+               status = zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP |
                        ZYNQ_I2C_INTERRUPT_DATA);
                if (!status) {
                        /* Release the bus */
@@ -241,27 +248,30 @@ static int zynq_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
                          int alen, u8 *data, int length)
 {
        u8 *cur_data = data;
+       struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
 
        /* Write the register address */
        setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
                ZYNQ_I2C_CONTROL_HOLD);
        clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW);
        writel(0xFF, &zynq_i2c->interrupt_status);
-       while (alen--)
-               writel(addr >> (8*alen), &zynq_i2c->data);
-       /* Start the tranfer */
        writel(dev, &zynq_i2c->address);
-       if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) {
-               /* Release the bus */
-               clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
-               return -ETIMEDOUT;
+       if (alen) {
+               while (alen--)
+                       writel(addr >> (8 * alen), &zynq_i2c->data);
+               /* Start the tranfer */
+               if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
+                       /* Release the bus */
+                       clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
+                       return -ETIMEDOUT;
+               }
+               debug("Device acked address\n");
        }
 
-       debug("Device acked address\n");
        while (length--) {
                writel(*(cur_data++), &zynq_i2c->data);
                if (readl(&zynq_i2c->transfer_size) == ZYNQ_I2C_FIFO_DEPTH) {
-                       if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) {
+                       if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
                                /* Release the bus */
                                clrbits_le32(&zynq_i2c->control,
                                             ZYNQ_I2C_CONTROL_HOLD);
@@ -273,7 +283,7 @@ static int zynq_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
        /* All done... release the bus */
        clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
        /* Wait for the address and data to be sent */
-       if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP))
+       if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP))
                return -ETIMEDOUT;
        return 0;
 }
@@ -291,3 +301,7 @@ U_BOOT_I2C_ADAP_COMPLETE(zynq_0, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read,
                         zynq_i2c_write, zynq_i2c_set_bus_speed,
                         CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE,
                         0)
+U_BOOT_I2C_ADAP_COMPLETE(zynq_1, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read,
+                        zynq_i2c_write, zynq_i2c_set_bus_speed,
+                        CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE,
+                        1)
index 26311741f5fa8b83bb51a9b1a1811571508b5c00..bd9b641135a11ae0c5e1373341aed44b7fab73a7 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/errno.h>
 #include <asm/byteorder.h>
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/sdh.h>
 #include <asm/mach-common/bits/dma.h>
index 42e208cfb60fcc79f0cd0fd1d565c3facf5543e8..0c2d2ef1a9671ad783d1d3da2cf9a04d2b793e96 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mii.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/dma.h>
 #include <asm/mach-common/bits/emac.h>
index aa89d89a32afa3c9e2710ff0214f50050a23f60e..71a31d0127fee425e428bf579159b09865c3274c 100644 (file)
@@ -13,6 +13,7 @@
 #include <spi.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/gpio.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/spi.h>
@@ -140,12 +141,12 @@ static const unsigned short cs_pins[][7] = {
 void spi_set_speed(struct spi_slave *slave, uint hz)
 {
        struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
-       ulong sclk;
+       ulong clk;
        u32 baud;
 
-       sclk = get_sclk();
+       clk = get_spi_clk();
        /* baud should be rounded up */
-       baud = DIV_ROUND_UP(sclk, 2 * hz);
+       baud = DIV_ROUND_UP(clk, 2 * hz);
        if (baud < 2)
                baud = 2;
        else if (baud > (u16)-1)
index 07b833d3a3de22b134b6d9ee4b1ffc6b422034f8..eba01d16f50d7d6f095cf87625624a7b33fd1ef7 100644 (file)
@@ -22,6 +22,7 @@
 #include <spi.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/gpio.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/spi6xx.h>
@@ -135,11 +136,11 @@ static const unsigned short cs_pins[][7] = {
 void spi_set_speed(struct spi_slave *slave, uint hz)
 {
        struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
-       ulong sclk;
+       ulong clk;
        u32 clock;
 
-       sclk = get_sclk1();
-       clock = sclk / hz;
+       clk = get_spi_clk();
+       clock = clk / hz;
        if (clock)
                clock--;
        bss->clock = clock;
index 35268ba58ef00b1c18e18ccecd7f0b0c85e3f0b9..65fff887d3ee2e2d50c199a9af337a5594849990 100644 (file)
@@ -11,6 +11,7 @@
 #include <usb.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/mach-common/bits/usb.h>
 
 #include "musb_core.h"
index e090a376d03cc3ae9e3679da81059e0408357f08..c0eba3721d70d30306f2ea9826d63a19547ac3e2 100644 (file)
 /* I2C driver configuration */
 #define CONFIG_HARD_I2C
 #define CONFIG_DW_I2C
+#if defined(CONFIG_SPEAR600)
+#define CONFIG_SYS_I2C_BASE                    0xD0200000
+#elif defined(CONFIG_SPEAR300)
+#define CONFIG_SYS_I2C_BASE                    0xD0180000
+#elif defined(CONFIG_SPEAR310)
+#define CONFIG_SYS_I2C_BASE                    0xD0180000
+#elif defined(CONFIG_SPEAR320)
+#define CONFIG_SYS_I2C_BASE                    0xD0180000
+#endif
 #define CONFIG_SYS_I2C_SPEED                   400000
 #define CONFIG_SYS_I2C_SLAVE                   0x02
 
index d420efe54389aba93f45899c60a5b75cc3381dfb..7405419f0e270a9ad6295cc8d9b6df6c6d40e327 100644 (file)
@@ -85,6 +85,7 @@
 /* I2C config options */
 #define CONFIG_HARD_I2C
 #define CONFIG_DW_I2C
+#define CONFIG_SYS_I2C_BASE                    0xD0200000
 #define CONFIG_SYS_I2C_SPEED                   400000
 #define CONFIG_SYS_I2C_SLAVE                   0x02
 #define CONFIG_I2C_CHIPADDRESS                 0x50
index c7eee0abe5b37183530c012d87983fc0b6b6282f..14f0b90b9bc968704cb85c2dcdf2de969866ad69 100644 (file)
 # define CONFIG_DOS_PARTITION
 #endif
 
+#define CONFIG_SYS_I2C_ZYNQ
 /* I2C */
-#if defined(CONFIG_ZYNQ_I2C0) || defined(CONFIG_ZYNQ_I2C1)
+#if defined(CONFIG_SYS_I2C_ZYNQ)
 # define CONFIG_CMD_I2C
 # define CONFIG_SYS_I2C
-# define CONFIG_SYS_I2C_ZYNQ
 # define CONFIG_SYS_I2C_ZYNQ_SPEED             100000
-# define CONFIG_SYS_I2C_ZYNQ_SLAVE             1
+# define CONFIG_SYS_I2C_ZYNQ_SLAVE             0
 #endif
 
 /* EEPROM */
index f93a18366e01dfd6dd8835c2ccdf207721ff08d0..1b4078ed62fe43c8c3ac37b1ff732da0d431d37f 100644 (file)
@@ -68,6 +68,7 @@ struct i2c_adapter {
        uint            (*set_bus_speed)(struct i2c_adapter *adap,
                                uint speed);
        int             speed;
+       int             waitdelay;
        int             slaveaddr;
        int             init_done;
        int             hwadapnr;