[U-Boot] [PATCH 3/9] apf9328: Add Armadeus Project board APF9328
Eric Jarrige
eric.jarrige at armadeus.org
Wed Aug 10 22:33:15 CEST 2011
Add Armadeus Project board APF9328
Signed-off-by: Eric Jarrige <eric.jarrige at armadeus.org>
Signed-off-by: Nicolas Colombain <nicolas.colombain at armadeus.com>
---
board/armadeus/apf9328/Makefile | 51 +++
board/armadeus/apf9328/apf9328.c | 91 ++++++
board/armadeus/apf9328/apf9328fpga.c | 89 ++++++
board/armadeus/apf9328/apf9328fpga.h | 31 ++
board/armadeus/apf9328/eeprom.c | 88 ++++++
board/armadeus/apf9328/fpga.c | 121 ++++++++
board/armadeus/apf9328/fpga.h | 30 ++
board/armadeus/apf9328/i2c.c | 276 +++++++++++++++++++
board/armadeus/apf9328/lowlevel_init.S | 469 ++++++++++++++++++++++++++++++++
9 files changed, 1246 insertions(+), 0 deletions(-)
create mode 100644 board/armadeus/apf9328/Makefile
create mode 100644 board/armadeus/apf9328/apf9328.c
create mode 100644 board/armadeus/apf9328/apf9328fpga.c
create mode 100644 board/armadeus/apf9328/apf9328fpga.h
create mode 100644 board/armadeus/apf9328/eeprom.c
create mode 100644 board/armadeus/apf9328/fpga.c
create mode 100644 board/armadeus/apf9328/fpga.h
create mode 100644 board/armadeus/apf9328/i2c.c
create mode 100644 board/armadeus/apf9328/lowlevel_init.S
diff --git a/board/armadeus/apf9328/Makefile b/board/armadeus/apf9328/Makefile
new file mode 100644
index 0000000..0f097cd
--- /dev/null
+++ b/board/armadeus/apf9328/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2004
+# 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$(BOARD).o
+
+COBJS := apf9328.o i2c.o apf9328fpga.o fpga.o eeprom.o
+SOBJS := lowlevel_init.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/armadeus/apf9328/apf9328.c b/board/armadeus/apf9328/apf9328.c
new file mode 100644
index 0000000..2250221
--- /dev/null
+++ b/board/armadeus/apf9328/apf9328.c
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright 2005-2011
+ * Nicolas Colombin <thom25 at users.sourceforge.net>
+ * Eric Jarrige <eric.jarrige at armadeus.org>
+ * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
+ *
+ * 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/arch/imx-regs.h>
+#include <flash.h>
+#include <netdev.h>
+#include "apf9328fpga.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+ gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
+ gd->bd->bi_boot_params = CONFIG_BOOT_PARAMS_ADDR;
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ /* dram_init must store complete ramsize in gd->ram_size */
+ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_1_BASE,
+ CONFIG_SYS_SDRAM_1_SIZE);
+ return 0;
+}
+
+void dram_init_banksize(void)
+{
+#if (CONFIG_NR_DRAM_BANKS > 0)
+ gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_1_BASE;
+ gd->bd->bi_dram[0].size = CONFIG_SYS_SDRAM_1_SIZE;
+#endif
+}
+
+/*
+ * Miscellaneous intialization
+ */
+int misc_init_r(void)
+{
+ char *s;
+
+#if (CONFIG_FPGA)
+ apf9328_init_fpga();
+#endif
+
+#if (CONFIG_DRIVER_DM9000)
+ imx_gpio_mode(GPIO_PORTB | GPIO_DR | GPIO_IN | 14);
+#endif
+
+ /* detect compatibility issue of environment version */
+ s = getenv("env_version");
+ if ((NULL == s) || (0 != strcmp(s, CONFIG_ENV_VERSION))) {
+ printf("*** Warning - Environment version change suggests: "
+ "run flash_reset_env; reset\n");
+ }
+
+ return 0;
+}
+
+void show_boot_progress(int status)
+{
+ return;
+}
+
+#ifdef CONFIG_DRIVER_DM9000
+int board_eth_init(bd_t *bis)
+{
+ return dm9000_initialize(bis);
+}
+#endif
diff --git a/board/armadeus/apf9328/apf9328fpga.c b/board/armadeus/apf9328/apf9328fpga.c
new file mode 100644
index 0000000..d64c0d4
--- /dev/null
+++ b/board/armadeus/apf9328/apf9328fpga.c
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2005-2011
+ * Nicolas Colombin <thom25 at users.sourceforge.net>
+ * Eric Jarrige <eric.jarrige at armadeus.org>
+ *
+ * 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
+ *
+ */
+
+/*
+ * Spartan 3 FPGA configuration support for the APF9328 daughter board
+ */
+
+#include <common.h>
+#include <spartan3.h>
+#include <command.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include "apf9328fpga.h"
+
+#if (CONFIG_FPGA)
+DECLARE_GLOBAL_DATA_PTR;
+/* Note that these are pointers to code that is in Flash. They will be
+ * relocated at runtime.
+ * Spartan3 code is used to download our Spartan 3 :) code is compatible.
+ * Just take care about the file size
+*/
+Xilinx_Spartan3_Slave_Serial_fns fpga_fns = {
+ fpga_pre_fn,
+ fpga_pgm_fn,
+ fpga_clk_fn,
+ fpga_init_fn,
+ fpga_done_fn,
+ fpga_wr_fn,
+};
+
+Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
+ {Xilinx_Spartan3,
+ slave_serial,
+ XILINX_XC3S400_SIZE,
+ (void *)&fpga_fns,
+ 0}
+};
+
+/*
+ * Initialize the fpga. Return 1 on success, 0 on failure.
+ */
+int apf9328_init_fpga(void)
+{
+ char *autoload = getenv("firmware_autoload");
+ int i, lout = 1;
+
+ debug("%s:%d: Initialize FPGA interface (relocation offset= 0x%.8lx)\n",
+ __func__, __LINE__, gd->reloc_off);
+
+ fpga_init();
+
+ for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
+ debug("%s:%d: Adding fpga %d\n", __func__, __LINE__, i);
+ fpga_add(fpga_xilinx, &fpga[i]);
+ }
+
+ if ((autoload) && (0 == strcmp(autoload, "1"))) {
+ if (FPGA_SUCCESS != fpga_load(0, (void *)CONFIG_FIRMWARE_ADDR,
+ (size_t) CONFIG_FIRMWARE_LEN)) {
+ lout = 0;
+ printf("Firmware not loaded!\n");
+ }
+ }
+ return 1;
+}
+
+#endif /* CONFIG_FPGA */
diff --git a/board/armadeus/apf9328/apf9328fpga.h b/board/armadeus/apf9328/apf9328fpga.h
new file mode 100644
index 0000000..2a15443
--- /dev/null
+++ b/board/armadeus/apf9328/apf9328fpga.h
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland at enterasys.com.
+ * Keith Outwater, keith_outwater at mvis.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
+ *
+ */
+
+/*
+ * Spartan 3 FPGA configuration support for the APF9328 daughter board
+ */
+
+#include "fpga.h"
+extern int apf9328_init_fpga(void);
diff --git a/board/armadeus/apf9328/eeprom.c b/board/armadeus/apf9328/eeprom.c
new file mode 100644
index 0000000..8f2ad9a
--- /dev/null
+++ b/board/armadeus/apf9328/eeprom.c
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2008-2011 Armadeus Project
+ * (C) Copyright 2007
+ * Stefano Babic, DENX Software Engineering, sbabic at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm9000.h>
+
+static int do_read_dm9000_eeprom(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ unsigned int i;
+ u8 data[2];
+
+ for (i = 0; i < 0x40; i++) {
+ if (!(i % 0x10))
+ printf("\n%08x:", i);
+ dm9000_read_srom_word(i, data);
+ printf(" %02x%02x", data[1], data[0]);
+ }
+ printf("\n");
+ return 0;
+}
+
+static int do_write_dm9000_eeprom(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ unsigned long offset, value;
+
+ if (argc < 4) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ strict_strtoul(argv[2], 16, &offset);
+ strict_strtoul(argv[3], 16, &value);
+ if (offset > 0x40) {
+ printf("Wrong offset : 0x%lx\n", offset);
+ cmd_usage(cmdtp);
+ return 1;
+ }
+ dm9000_write_srom_word(offset, value);
+ return 0;
+}
+
+int do_dm9000_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ if (argc < 2) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ if (strcmp(argv[1], "read") == 0) {
+ return do_read_dm9000_eeprom(cmdtp, flag, argc, argv);
+ } else if (strcmp(argv[1], "write") == 0) {
+ return do_write_dm9000_eeprom(cmdtp, flag, argc, argv);
+ } else {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+}
+
+U_BOOT_CMD(dm9000ee, 4, 1, do_dm9000_eeprom,
+ "Read/Write eeprom connected to Ethernet Controller",
+ "\ndm9000ee write <word offset> <value> \n"
+ "\tdm9000ee read \n"
+ "\tword:\t\t00-02 : MAC Address\n"
+ "\t\t\t03-07 : DM9000 Configuration\n" "\t\t\t08-63 : User data");
diff --git a/board/armadeus/apf9328/fpga.c b/board/armadeus/apf9328/fpga.c
new file mode 100644
index 0000000..ec4c251
--- /dev/null
+++ b/board/armadeus/apf9328/fpga.c
@@ -0,0 +1,121 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland at enterasys.com.
+ * Keith Outwater, keith_outwater at mvis.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 <common.h>
+
+#if (CONFIG_FPGA)
+
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include <config.h>
+
+#define GPIO_PORT(x) ((x >> 5) & 3)
+#define GPIO_SET(x) (DR(GPIO_PORT(x)) |= (1<<(x & GPIO_PIN_MASK)))
+#define GPIO_CLEAR(x) (DR(GPIO_PORT(x)) &= ~(1<<(x & GPIO_PIN_MASK)))
+#define GPIO_WRITE(x, y) (y ? GPIO_SET(x) : GPIO_CLEAR(x))
+#define GPIO_READ(x) ((SSR(GPIO_PORT(x)) & (1<<(x & GPIO_PIN_MASK))))
+
+/*
+ * Port bit numbers for the serial slave controls
+ */
+#define FPGA_INIT CONFIG_SYS_FPGA_INIT
+#define FPGA_DONE CONFIG_SYS_FPGA_DONE
+#define FPGA_DIN CONFIG_SYS_FPGA_DATA
+#define FPGA_PROGRAM CONFIG_SYS_FPGA_PRG
+#define FPGA_CLOCK CONFIG_SYS_FPGA_CLK
+
+/* Note that these are pointers to code that is in Flash. They will be
+ * relocated at runtime.
+ * Spartan2 code is used to download our Spartan 3 :) code is compatible.
+ * Just take care about the file size
+*/
+
+/*
+ * nitialize GPIO port B before download
+ */
+int fpga_pre_fn(int cookie)
+{
+ debug("%s:%d: FPGA PRE ", __func__, __LINE__);
+
+ /* Initialize GPIO pins */
+ imx_gpio_mode(FPGA_INIT | GPIO_DR | GPIO_IN);
+ imx_gpio_mode(FPGA_DONE | GPIO_DR | GPIO_IN);
+ imx_gpio_mode(FPGA_DIN | GPIO_DR | GPIO_OUT);
+ imx_gpio_mode(FPGA_PROGRAM | GPIO_DR | GPIO_OUT);
+ imx_gpio_mode(FPGA_CLOCK | GPIO_DR | GPIO_OUT);
+ return cookie;
+}
+
+/*
+ * Set the FPGA's active-low program line to the specified level
+ */
+int fpga_pgm_fn(int assert, int flush, int cookie)
+{
+ debug("%s:%d: FPGA PROGRAM %s", __func__, __LINE__,
+ assert ? "high" : "low");
+ GPIO_WRITE(FPGA_PROGRAM, !assert);
+ return assert;
+}
+
+/*
+ * Set the FPGA's active-high clock line to the specified level
+ */
+int fpga_clk_fn(int assert_clk, int flush, int cookie)
+{
+ debug("%s:%d: FPGA CLOCK %s", __func__, __LINE__,
+ assert_clk ? "high" : "low");
+ GPIO_WRITE(FPGA_CLOCK, assert_clk);
+ return assert_clk;
+}
+
+/*
+ * Test the state of the active-low FPGA INIT line. Return 1 on INIT
+ * asserted (low).
+ */
+int fpga_init_fn(int cookie)
+{
+ debug("%s:%d: INIT check... ", __func__, __LINE__);
+ return !GPIO_READ(FPGA_INIT);
+}
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int fpga_done_fn(int cookie)
+{
+ debug("%s:%d: DONE check... ", __func__, __LINE__);
+ return GPIO_READ(FPGA_DONE);
+}
+
+/*
+ * Set the FPGA's data line to the specified level
+ */
+int fpga_wr_fn(int assert_write, int flush, int cookie)
+{
+ debug("%s:%d: DATA write... ", __func__, __LINE__);
+ GPIO_WRITE(FPGA_DIN, assert_write);
+ return assert_write;
+}
+
+#endif /* CONFIG_FPGA */
diff --git a/board/armadeus/apf9328/fpga.h b/board/armadeus/apf9328/fpga.h
new file mode 100644
index 0000000..3b226d7
--- /dev/null
+++ b/board/armadeus/apf9328/fpga.h
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland at enterasys.com.
+ * Keith Outwater, keith_outwater at mvis.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
+ *
+ */
+extern int fpga_pre_fn(int cookie);
+extern int fpga_pgm_fn(int assert_pgm, int flush, int cookie);
+extern int fpga_init_fn(int cookie);
+extern int fpga_done_fn(int cookie);
+extern int fpga_clk_fn(int assert_clk, int flush, int cookie);
+extern int fpga_wr_fn(int assert_write, int flush, int cookie);
diff --git a/board/armadeus/apf9328/i2c.c b/board/armadeus/apf9328/i2c.c
new file mode 100644
index 0000000..0ba0a8d
--- /dev/null
+++ b/board/armadeus/apf9328/i2c.c
@@ -0,0 +1,276 @@
+/*
+ * (C) Copyright 2005-2011 ej Armadeus Project <eric.jarrige at armadeus.org>
+ *
+ * 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>
+
+#ifdef CONFIG_HARD_I2C
+
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <i2c.h>
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+#define I2C_ACK 0 /* level to ack a byte */
+#define I2C_NOACK 1 /* level to noack a byte */
+
+/*-----------------------------------------------------------------------
+ * Local functions
+ */
+
+/*-----------------------------------------------------------------------
+ * START: High -> Low on SDA while SCL is High
+ * after check for a bus free
+ */
+static void imxi2c_send_start(void)
+{
+ while (I2SR & I2SR_IBB)
+ udelay(1);
+
+ I2CR |= I2CR_MSTA;
+ I2SR &= ~I2SR_IIF;
+}
+
+/*-----------------------------------------------------------------------
+ * STOP: Low -> High on SDA while SCL is High
+ * after the end of previous transfer
+ */
+static void imxi2c_send_stop(void)
+{
+ while (!(I2SR & I2SR_ICF))
+ udelay(1);
+
+ I2CR &= ~I2CR_MSTA;
+}
+
+/*-----------------------------------------------------------------------
+ * Send 8 bits and look for an acknowledgement.
+ */
+static int imxi2c_write_byte(uchar data)
+{
+ while (!(I2SR & I2SR_ICF)) /* Wait end of transfer */
+ udelay(1);
+
+ I2CR |= I2CR_MTX;
+ I2SR &= ~I2SR_IIF;
+ I2DR = data;
+
+ while (!(I2SR & I2SR_IIF)) /* checking IIF before ICF: FIXME */
+ udelay(1);
+
+ I2SR &= ~I2SR_IIF;
+
+ while (!(I2SR & I2SR_ICF)) /* Wait end of transfer */
+ udelay(1);
+
+ return I2SR & I2SR_RXAK; /* not a nack is an ack */
+}
+
+/*-----------------------------------------------------------------------
+ * if ack == I2C_ACK, ACK the byte so can continue reading, else
+ * send I2C_NOACK to end the read.
+ */
+static uchar imxi2c_read_byte(int ack)
+{
+ int data;
+
+ while (!(I2SR & I2SR_ICF))
+ udelay(1);
+
+ I2CR &= ~I2CR_MTX;
+
+ if (ack)
+ I2CR |= I2CR_TXAK;
+ else
+ I2CR &= ~I2CR_TXAK;
+
+ data = I2DR;
+ return data;
+}
+
+/* ------------------------------------------------------------------------
+ * API Functions
+ * ------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------
+ * i2c_init compute the i2c divider to reach the requested speed
+ * see mxl reference manual
+ */
+void i2c_init(int speed, int slaveaddr)
+{
+ int hclk_dividers[] = {
+ 30, 32, 36, 42, 48, 52, 60, 72,
+ 80, 88, 104, 128, 144, 160, 192, 240,
+ 288, 320, 384, 480, 576, 640, 768, 960,
+ 1152, 1280, 1536, 1920, 2304, 2560, 3072, 3840,
+ 22, 24, 26, 26, 32, 36, 40, 44,
+ 48, 56, 64, 72, 80, 96, 112, 128,
+ 160, 192, 224, 256, 320, 384, 448, 512,
+ 640, 768, 896, 1024, 1280, 1536, 1792, 2048
+ };
+ int refDiv = get_HCLK() / speed;
+ int i, tmpIC;
+
+ imx_gpio_mode(PA15_PF_I2C_SDA);
+ imx_gpio_mode(PA16_PF_I2C_SCL);
+
+ tmpIC = (sizeof(hclk_dividers) / sizeof(int)) - 1;
+ for (i = tmpIC; i >= 0; i--) {
+ if ((hclk_dividers[i] >= refDiv)
+ && (hclk_dividers[i] < hclk_dividers[tmpIC])) {
+ tmpIC = i;
+ }
+ }
+
+ IFDR = tmpIC;
+ IADR = slaveaddr << 1;
+
+ if (I2SR & I2SR_IBB)
+ imxi2c_send_stop();
+
+ I2CR |= I2CR_IEN;
+}
+
+/*-----------------------------------------------------------------------
+ * Probe to see if a chip is present. Also good for checking for the
+ * completion of EEPROM writes since the chip stops responding until
+ * the write completes (typically 10mSec).
+ * probe sends a read command to probe a an address
+ */
+int i2c_probe(uchar addr)
+{
+ int rc;
+
+ imxi2c_send_start();
+ rc = imxi2c_write_byte((addr << 1) | 0);
+ imxi2c_send_stop();
+
+ return rc ? 1 : 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Read bytes
+ */
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+ int shift;
+ debug("i2c_read: chip %02X addr %02X alen %d buffer %p len %d\n",
+ chip, addr, alen, buffer, len);
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+ /*
+ * EEPROM chips that implement "address overflow" are ones
+ * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
+ * address and the extra bits end up in the "chip address"
+ * bit slots. This makes a 24WC08 (1Kbyte) chip look like
+ * four 256 byte chips.
+ *
+ * Note that we consider the length of the address field to
+ * still be one byte because the extra address bits are
+ * hidden in the chip address.
+ */
+ chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+
+ debug("i2c_read: fix addr_overflow: chip %02X addr %02X\n",
+ chip, addr);
+#endif
+
+ /*
+ * Do the addressing portion of a write cycle to set the
+ * chip's address pointer. If the address length is zero,
+ * don't do the normal write cycle to set the address pointer,
+ * there is no address pointer in this chip.
+ */
+ imxi2c_send_start();
+ if (alen > 0) {
+ if (imxi2c_write_byte(chip << 1)) { /* write cycle */
+ imxi2c_send_stop();
+ debug("i2c_read, no chip responded %02X\n", chip);
+ return 1;
+ }
+ shift = (alen - 1) * 8;
+ while (alen-- > 0) {
+ if (imxi2c_write_byte(addr >> shift)) {
+ debug("i2c_read, address not <ACK>ed\n");
+ return 1;
+ }
+ shift -= 8;
+ }
+
+ /* reportedly some chips need a full stop */
+ imxi2c_send_stop();
+ imxi2c_send_start();
+ }
+ /*
+ * Send the chip address again, this time for a read cycle.
+ * Then read the data. On the last byte, we do a NACK instead
+ * of an ACK(len == 0) to terminate the read.
+ */
+ imxi2c_write_byte((chip << 1) | 1); /* read cycle */
+ imxi2c_read_byte(len <= 2);
+ while (len-- > 1)
+ *buffer++ = imxi2c_read_byte(len == 1);
+
+ imxi2c_send_stop();
+ *buffer++ = imxi2c_read_byte(0);
+ return 0;
+}
+
+/*-----------------------------------------------------------------------
+ * Write bytes
+ */
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+ int shift, failures = 0;
+
+ debug("i2c_write: chip %02X addr %02X alen %d buffer %p len %d\n",
+ chip, addr, alen, buffer, len);
+
+ imxi2c_send_start();
+ if (imxi2c_write_byte(chip << 1)) { /* write cycle */
+ imxi2c_send_stop();
+ debug("i2c_write, no chip responded %02X\n", chip);
+ return 1;
+ }
+ shift = (alen - 1) * 8;
+ while (alen-- > 0) {
+ if (imxi2c_write_byte(addr >> shift)) {
+ debug("i2c_write, address not <ACK>ed\n");
+ return 1;
+ }
+ shift -= 8;
+ }
+
+ while (len-- > 0) {
+ if (imxi2c_write_byte(*buffer++))
+ failures++;
+ }
+ imxi2c_send_stop();
+ return failures;
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/board/armadeus/apf9328/lowlevel_init.S b/board/armadeus/apf9328/lowlevel_init.S
new file mode 100644
index 0000000..e4c6157
--- /dev/null
+++ b/board/armadeus/apf9328/lowlevel_init.S
@@ -0,0 +1,469 @@
+/*
+ * (C) Copyright 2005-2011 ej Armadeus Project <eric.jarrige at armadeus.org>
+ * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
+ *
+ * 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 <version.h>
+#include <asm/arch/imx-regs.h>
+
+.globl lowlevel_init
+lowlevel_init:
+/* Change PERCLK1DIV to 14 ie 14+1 */
+ ldr r0, =PCDR
+ ldr r1, =CONFIG_SYS_PCDR_VAL
+ str r1, [r0]
+
+/* set MCU PLL Control Register 0 */
+
+ ldr r0, =MPCTL0
+ ldr r1, =CONFIG_SYS_MPCTL0_VAL
+ str r1, [r0]
+
+/* set MCU PLL Control Register 1 */
+
+ ldr r0, =MPCTL1
+ ldr r1, =CONFIG_SYS_MPCTL1_VAL
+ str r1, [r0]
+
+/* set mpll restart bit */
+ ldr r0, =CSCR
+ ldr r1, [r0]
+ orr r1,r1,#(1<<21)
+ str r1, [r0]
+
+ mov r2,#0x10
+1:
+ mov r3,#0x2000
+2:
+ subs r3,r3,#1
+ bne 2b
+
+ subs r2,r2,#1
+ bne 1b
+
+/* set System PLL Control Register 0 */
+
+ ldr r0, =SPCTL0
+ ldr r1, =CONFIG_SYS_SPCTL0_VAL
+ str r1, [r0]
+
+/* set System PLL Control Register 1 */
+
+ ldr r0, =SPCTL1
+ ldr r1, =CONFIG_SYS_SPCTL1_VAL
+ str r1, [r0]
+
+/* set spll restart bit */
+ ldr r0, =CSCR
+ ldr r1, [r0]
+ orr r1,r1,#(1<<22)
+ str r1, [r0]
+
+ mov r2,#0x10
+1:
+ mov r3,#0x2000
+2:
+ subs r3,r3,#1
+ bne 2b
+
+ subs r2,r2,#1
+ bne 1b
+
+ ldr r0, =CSCR
+ ldr r1, =CONFIG_SYS_CSCR_VAL
+ str r1, [r0]
+
+ ldr r0, =GPCR
+ ldr r1, =CONFIG_SYS_GPCR_VAL
+ str r1, [r0]
+
+/* I have now read the ARM920 DataSheet back-to-Back, and have stumbled upon
+ *this.....
+ *
+ * It would appear that from a Cold-Boot the ARM920T enters "FastBus" mode CP15
+ * register 1, this stops it using the output of the PLL and thus runs at the
+ * slow rate. Unless you place the Core into "Asynch" mode, the CPU will never
+ * use the value set in the CM_OSC registers...regardless of what you set it
+ * too! Thus, although i thought i was running at 140MHz, i'm actually running
+ * at 40!..
+
+ * Slapping this into my bootloader does the trick...
+
+ * MRC p15,0,r0,c1,c0,0 ; read core configuration register
+ * ORR r0,r0,#0xC0000000 ; set asynchronous clocks and not fastbus mode
+ * MCR p15,0,r0,c1,c0,0 ; write modified value to core configuration
+ * register
+ */
+ MRC p15,0,r0,c1,c0,0
+ ORR r0,r0,#0xC0000000
+ MCR p15,0,r0,c1,c0,0
+
+/* ldr r0, =GPR(0)
+ ldr r1, =CONFIG_SYS_GPR_A_VAL
+ str r1, [r0]
+*/
+
+ ldr r0, =DR(0)
+ ldr r1, =CONFIG_SYS_DR_A_VAL
+ str r1, [r0]
+
+ ldr r0, =OCR1(0)
+ ldr r1, =CONFIG_SYS_OCR1_A_VAL
+ str r1, [r0]
+
+ ldr r0, =OCR2(0)
+ ldr r1, =CONFIG_SYS_OCR2_A_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFA1(0)
+ ldr r1, =CONFIG_SYS_ICFA1_A_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFA2(0)
+ ldr r1, =CONFIG_SYS_ICFA2_A_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFB1(0)
+ ldr r1, =CONFIG_SYS_ICFB1_A_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFB2(0)
+ ldr r1, =CONFIG_SYS_ICFB2_A_VAL
+ str r1, [r0]
+
+ ldr r0, =ICR1(0)
+ ldr r1, =CONFIG_SYS_ICR1_A_VAL
+ str r1, [r0]
+
+ ldr r0, =ICR2(0)
+ ldr r1, =CONFIG_SYS_ICR2_A_VAL
+ str r1, [r0]
+
+ ldr r0, =IMR(0)
+ ldr r1, =CONFIG_SYS_IMR_A_VAL
+ str r1, [r0]
+
+ ldr r0, =DDIR(0)
+ ldr r1, =CONFIG_SYS_DDIR_A_VAL
+ str r1, [r0]
+
+ ldr r0, =GPR(0)
+ ldr r1, =CONFIG_SYS_GPR_A_VAL
+ str r1, [r0]
+
+ ldr r0, =PUEN(0)
+ ldr r1, =CONFIG_SYS_PUEN_A_VAL
+ str r1, [r0]
+
+ ldr r0, =GIUS(0)
+ ldr r1, =CONFIG_SYS_GIUS_A_VAL
+ str r1, [r0]
+
+ ldr r0, =DR(1)
+ ldr r1, =CONFIG_SYS_DR_B_VAL
+ str r1, [r0]
+
+ ldr r0, =OCR1(1)
+ ldr r1, =CONFIG_SYS_OCR1_B_VAL
+ str r1, [r0]
+
+ ldr r0, =OCR2(1)
+ ldr r1, =CONFIG_SYS_OCR2_B_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFA1(1)
+ ldr r1, =CONFIG_SYS_ICFA1_B_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFA2(1)
+ ldr r1, =CONFIG_SYS_ICFA2_B_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFB1(1)
+ ldr r1, =CONFIG_SYS_ICFB1_B_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFB2(1)
+ ldr r1, =CONFIG_SYS_ICFB2_B_VAL
+ str r1, [r0]
+
+ ldr r0, =ICR1(1)
+ ldr r1, =CONFIG_SYS_ICR1_B_VAL
+ str r1, [r0]
+
+ ldr r0, =ICR2(1)
+ ldr r1, =CONFIG_SYS_ICR2_B_VAL
+ str r1, [r0]
+
+ ldr r0, =IMR(1)
+ ldr r1, =CONFIG_SYS_IMR_B_VAL
+ str r1, [r0]
+
+ ldr r0, =DDIR(1)
+ ldr r1, =CONFIG_SYS_DDIR_B_VAL
+ str r1, [r0]
+
+ ldr r0, =GPR(1)
+ ldr r1, =CONFIG_SYS_GPR_B_VAL
+ str r1, [r0]
+
+ ldr r0, =PUEN(1)
+ ldr r1, =CONFIG_SYS_PUEN_B_VAL
+ str r1, [r0]
+
+ ldr r0, =GIUS(1)
+ ldr r1, =CONFIG_SYS_GIUS_B_VAL
+ str r1, [r0]
+
+ ldr r0, =DR(2)
+ ldr r1, =CONFIG_SYS_DR_C_VAL
+ str r1, [r0]
+
+ ldr r0, =OCR1(2)
+ ldr r1, =CONFIG_SYS_OCR1_C_VAL
+ str r1, [r0]
+
+ ldr r0, =OCR2(2)
+ ldr r1, =CONFIG_SYS_OCR2_C_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFA1(2)
+ ldr r1, =CONFIG_SYS_ICFA1_C_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFA2(2)
+ ldr r1, =CONFIG_SYS_ICFA2_C_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFB1(2)
+ ldr r1, =CONFIG_SYS_ICFB1_C_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFB2(2)
+ ldr r1, =CONFIG_SYS_ICFB2_C_VAL
+ str r1, [r0]
+
+ ldr r0, =ICR1(2)
+ ldr r1, =CONFIG_SYS_ICR1_C_VAL
+ str r1, [r0]
+
+ ldr r0, =ICR2(2)
+ ldr r1, =CONFIG_SYS_ICR2_C_VAL
+ str r1, [r0]
+
+ ldr r0, =IMR(2)
+ ldr r1, =CONFIG_SYS_IMR_C_VAL
+ str r1, [r0]
+
+ ldr r0, =DDIR(2)
+ ldr r1, =CONFIG_SYS_DDIR_C_VAL
+ str r1, [r0]
+
+ ldr r0, =GPR(2)
+ ldr r1, =CONFIG_SYS_GPR_C_VAL
+ str r1, [r0]
+
+ ldr r0, =PUEN(2)
+ ldr r1, =CONFIG_SYS_PUEN_C_VAL
+ str r1, [r0]
+
+ ldr r0, =GIUS(2)
+ ldr r1, =CONFIG_SYS_GIUS_C_VAL
+ str r1, [r0]
+
+ ldr r0, =DR(3)
+ ldr r1, =CONFIG_SYS_DR_D_VAL
+ str r1, [r0]
+
+ ldr r0, =OCR1(3)
+ ldr r1, =CONFIG_SYS_OCR1_D_VAL
+ str r1, [r0]
+
+ ldr r0, =OCR2(3)
+ ldr r1, =CONFIG_SYS_OCR2_D_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFA1(3)
+ ldr r1, =CONFIG_SYS_ICFA1_D_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFA2(3)
+ ldr r1, =CONFIG_SYS_ICFA2_D_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFB1(3)
+ ldr r1, =CONFIG_SYS_ICFB1_D_VAL
+ str r1, [r0]
+
+ ldr r0, =ICONFB2(3)
+ ldr r1, =CONFIG_SYS_ICFB2_D_VAL
+ str r1, [r0]
+
+ ldr r0, =ICR1(3)
+ ldr r1, =CONFIG_SYS_ICR1_D_VAL
+ str r1, [r0]
+
+ ldr r0, =ICR2(3)
+ ldr r1, =CONFIG_SYS_ICR2_D_VAL
+ str r1, [r0]
+
+ ldr r0, =IMR(3)
+ ldr r1, =CONFIG_SYS_IMR_D_VAL
+ str r1, [r0]
+
+ ldr r0, =DDIR(3)
+ ldr r1, =CONFIG_SYS_DDIR_D_VAL
+ str r1, [r0]
+
+ ldr r0, =GPR(3)
+ ldr r1, =CONFIG_SYS_GPR_D_VAL
+ str r1, [r0]
+
+ ldr r0, =PUEN(3)
+ ldr r1, =CONFIG_SYS_PUEN_D_VAL
+ str r1, [r0]
+
+ ldr r0, =GIUS(3)
+ ldr r1, =CONFIG_SYS_GIUS_D_VAL
+ str r1, [r0]
+
+/* CS3 becomes CS3 by clearing reset default bit 1 in FMCR */
+
+ ldr r0, =FMCR
+ ldr r1, =CONFIG_SYS_FMCR_VAL
+ str r1, [r0]
+
+ ldr r0, =CS0U
+ ldr r1, =CONFIG_SYS_CS0U_VAL
+ str r1, [r0]
+
+ ldr r0, =CS0L
+ ldr r1, =CONFIG_SYS_CS0L_VAL
+ str r1, [r0]
+
+ ldr r0, =CS1U
+ ldr r1, =CONFIG_SYS_CS1U_VAL
+ str r1, [r0]
+
+ ldr r0, =CS1L
+ ldr r1, =CONFIG_SYS_CS1L_VAL
+ str r1, [r0]
+
+ ldr r0, =CS2U
+ ldr r1, =CONFIG_SYS_CS2U_VAL
+ str r1, [r0]
+
+ ldr r0, =CS2L
+ ldr r1, =CONFIG_SYS_CS2L_VAL
+ str r1, [r0]
+
+ ldr r0, =CS3U
+ ldr r1, =CONFIG_SYS_CS3U_VAL
+ str r1, [r0]
+
+ ldr r0, =CS3L
+ ldr r1, =CONFIG_SYS_CS3L_VAL
+ str r1, [r0]
+
+ ldr r0, =CS4U
+ ldr r1, =CONFIG_SYS_CS4U_VAL
+ str r1, [r0]
+
+ ldr r0, =CS4L
+ ldr r1, =CONFIG_SYS_CS4L_VAL
+ str r1, [r0]
+
+ ldr r0, =CS5U
+ ldr r1, =CONFIG_SYS_CS5U_VAL
+ str r1, [r0]
+
+ ldr r0, =CS5L
+ ldr r1, =CONFIG_SYS_CS5L_VAL
+ str r1, [r0]
+
+ adr r0, sdramsetup /* r0 <- current position of code */
+ /* test if we run from flash or RAM */
+ ldr r1, =CONFIG_SYS_SDRAM_1_BASE
+ cmp r1, r0 /* don't reloc during debug*/
+ bhi sdramsetup
+ /* test if we run from flash or RAM */
+ ldr r1, =CONFIG_SYS_FLASH_BASE
+ cmp r0, r1 /* don't reloc during debug */
+ bmi copy2ram
+
+/* SDRAM Setup */
+sdramsetup:
+ ldr r0, =SDCTL0
+ ldr r1, =CONFIG_SYS_PRECHARGE_CMD
+ str r1, [r0]
+
+ ldr r1, =CONFIG_SYS_SDRAM_1_BASE \
+ +CONFIG_SYS_SDRAM_PRECHARGE_ALL_VAL
+ ldr r2, [r1]
+
+ ldr r1, =CONFIG_SYS_AUTOREFRESH_CMD
+ str r1, [r0]
+
+ ldr r1, =CONFIG_SYS_SDRAM_1_BASE
+ ldr r2, [r1] /* Issue AutoRefresh Command */
+ ldr r2, [r1]
+ ldr r2, [r1]
+ ldr r2, [r1]
+ ldr r2, [r1]
+ ldr r2, [r1]
+ ldr r2, [r1]
+ ldr r2, [r1]
+
+ ldr r1, =CONFIG_SYS_SET_MODE_REG_CMD
+ str r1, [r0]
+
+ ldr r1, =CONFIG_SYS_SDRAM_1_BASE \
+ +CONFIG_SYS_SDRAM_MODE_REGISTER_VAL
+ str r2, [r1]
+
+ ldr r1, =CONFIG_SYS_NORMAL_RW_CMD
+ str r1, [r0]
+/* make U-Boot runnable form "almost" anywhere */
+/* but SYS_TEXT_BASE should be in RAM */
+copy2ram: /* populate _TEXT_BASE with U-Boot from load addr */
+ ldr r0, _start_adr
+ ldr r1, _copy2ram
+ sub r1, r1, r0
+ adr r0, copy2ram
+ sub r0, r0, r1
+ ldr r1, =CONFIG_SYS_TEXT_BASE
+ cmp r0, r1
+ beq end_of_copy2ram /* skip U-Boot copy */
+ ldr r2, =CONFIG_SYS_MONITOR_LEN
+ add r2, r2, r0 /* r2 <- source end address */
+
+copy_loop:
+ ldmia r0!, {r9-r10} /* copy from source address [r0] */
+ stmia r1!, {r9-r10} /* copy to target address [r1] */
+ cmp r0, r2 /* until source end address [r2] */
+ blo copy_loop
+
+end_of_copy2ram:
+ mov pc,lr
+
+_copy2ram:
+ .word copy2ram
+_start_adr:
+ .word _start
More information about the U-Boot
mailing list