From patchwork Wed Aug 10 20:33:15 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Jarrige X-Patchwork-Id: 109454 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 6FB93B6F80 for ; Thu, 11 Aug 2011 07:11:00 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 42FBC283F1; Wed, 10 Aug 2011 23:08:21 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ar9AEPbl4JMU; Wed, 10 Aug 2011 23:08:20 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9B4B428406; Wed, 10 Aug 2011 23:07:53 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5FDD2283E1 for ; Wed, 10 Aug 2011 23:07:22 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nT39iSXe6AQL for ; Wed, 10 Aug 2011 23:07:06 +0200 (CEST) X-policyd-weight: passed - too many local DNS-errors in dnsbl.njabl.org lookups Received: from mo5.mail-out.ovh.net (7.mo5.mail-out.ovh.net [178.32.124.100]) by theia.denx.de (Postfix) with ESMTP id 60AD6283DB for ; Wed, 10 Aug 2011 23:06:32 +0200 (CEST) Received: from mail409.ha.ovh.net (b7.ovh.net [213.186.33.57]) by mo5.mail-out.ovh.net (Postfix) with SMTP id 7586910008B3 for ; Wed, 10 Aug 2011 22:26:55 +0200 (CEST) Received: from b0.ovh.net (HELO queueout) (213.186.33.50) by b0.ovh.net with SMTP; 10 Aug 2011 22:26:46 +0200 Received: from 85-218-50-42.dclient.lsne.ch (HELO shuttle2.etheralp.ch) (85.218.50.42) by ns0.ovh.net with SMTP; 10 Aug 2011 22:26:44 +0200 Received: from localhost ([127.0.0.1] helo=shuttle2.etheralp.ch) by shuttle2.etheralp.ch with esmtp (Exim 4.72) (envelope-from ) id 1QrFSl-0005a6-JN; Wed, 10 Aug 2011 22:33:15 +0200 X-Ovh-Mailout: 178.32.228.5 (mo5.mail-out.ovh.net) To: u-boot@lists.denx.de From: Eric Jarrige Date: Wed, 10 Aug 2011 22:33:15 +0200 Message-ID: <20110810203315.21204.35859.stgit@shuttle2.etheralp.ch> In-Reply-To: <20110810200828.21204.60050.stgit@shuttle2.etheralp.ch> References: <20110810200828.21204.60050.stgit@shuttle2.etheralp.ch> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Ovh-Tracer-Id: 16826574109202464026 X-Ovh-Remote: 85.218.50.42 (85-218-50-42.dclient.lsne.ch) X-Ovh-Local: 213.186.33.20 (ns0.ovh.net) X-Spam-Check: DONE|U 0.5/N X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfedvjedrtdejucetggdotefuucfrrhhofhhilhgvmecuqfggjfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Cc: Nicolas Colombain , biggerbadderben@gmail.com Subject: [U-Boot] [PATCH 3/9] apf9328: Add Armadeus Project board APF9328 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Add Armadeus Project board APF9328 Signed-off-by: Eric Jarrige Signed-off-by: Nicolas Colombain --- 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@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 + * Eric Jarrige + * 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 +#include +#include +#include +#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 + * Eric Jarrige + * + * 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 +#include +#include +#include +#include +#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@enterasys.com. + * Keith Outwater, keith_outwater@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@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 +#include +#include + +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 \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@enterasys.com. + * Keith Outwater, keith_outwater@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 + +#if (CONFIG_FPGA) + +#include +#include +#include + +#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@enterasys.com. + * Keith Outwater, keith_outwater@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 + * + * 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 + +#ifdef CONFIG_HARD_I2C + +#include +#include +#include + +/*----------------------------------------------------------------------- + * 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 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 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 + * 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 +#include +#include + +.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