diff options
author | Sudhakar Rajashekhara <sudhakar.raj@ti.com> | 2009-02-27 03:24:43 -0500 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2009-09-09 14:03:17 -0400 |
commit | 639b8447b44c3f636ef11093899f772be0c55ea6 (patch) | |
tree | b029316c662d0497ab1ecb101c871eaaea2d6c45 | |
parent | 72d15e705bc3983884105cb7755c7ba80e74a0a5 (diff) |
Primus port of u-boot.
Tested for SPI and NAND boot mode on Primus EVM.
Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
36 files changed, 13768 insertions, 6 deletions
@@ -151,7 +151,8 @@ ifeq ($(ARCH),ppc) CROSS_COMPILE = ppc_8xx- endif ifeq ($(ARCH),arm) -CROSS_COMPILE = arm-linux- +#CROSS_COMPILE = arm-linux- +CROSS_COMPILE = arm-none-linux-gnueabi- endif ifeq ($(ARCH),i386) CROSS_COMPILE = i386-linux- @@ -2715,6 +2716,9 @@ davinci_sffsdr_config : unconfig davinci_sonata_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm926ejs sonata davinci davinci +da8xx_evm_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs da8xx-evm da8xx da8xx + lpd7a400_config \ lpd7a404_config: unconfig @$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x diff --git a/board/da8xx/da8xx-evm/Makefile b/board/da8xx/da8xx-evm/Makefile new file mode 100644 index 0000000000..fa0013811d --- /dev/null +++ b/board/da8xx/da8xx-evm/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# 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).a + +COBJS := dv_board.o +SOBJS := board_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak *~ .depend + +######################################################################### +# This is for $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/da8xx/da8xx-evm/board_init.S b/board/da8xx/da8xx-evm/board_init.S new file mode 100644 index 0000000000..22d8adc18c --- /dev/null +++ b/board/da8xx/da8xx-evm/board_init.S @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Board-specific low level initialization code. Called at the very end + * of cpu/arm926ejs/davinci/lowlevel_init.S. Just returns if there is no + * initialization required. + * + * 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> + +.globl dv_board_init +dv_board_init: + + mov pc, lr diff --git a/board/da8xx/da8xx-evm/config.mk b/board/da8xx/da8xx-evm/config.mk new file mode 100644 index 0000000000..56de37a08f --- /dev/null +++ b/board/da8xx/da8xx-evm/config.mk @@ -0,0 +1,30 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> +# +# (C) Copyright 2003 +# Texas Instruments, <www.ti.com> +# Swaminathan <swami.iyer@ti.com> +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# (C) Copyright 2008 +# Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> +# +# Texas Instruments DA8xx EVM board (ARM925EJS) cpu +# see http://www.ti.com/ for more information on Texas Instruments +# +# DA8xx EVM has 1 bank of 64 MB SDRAM (2 16Meg x16 chips). +# Physical Address: +# C000'0000 to C400'0000 +# +# Linux-Kernel is expected to be at C000'8000, entry C000'8000 +# (mem base + reserved) +# +# we load ourself to C108 '0000 +# +# + +#Provide at least 16MB spacing between us and the Linux Kernel image +TEXT_BASE = 0xC1080000 diff --git a/board/da8xx/da8xx-evm/dv_board.c b/board/da8xx/da8xx-evm/dv_board.c new file mode 100644 index 0000000000..d6eff61242 --- /dev/null +++ b/board/da8xx/da8xx-evm/dv_board.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> + * + * Modified for DA8xx EVM. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Parts are shamelessly stolen from various TI sources, original copyright + * follows: + * ----------------------------------------------------------------- + * + * Copyright (C) 2004 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + */ + +#include <common.h> +#include <i2c.h> +#include <asm/arch/hardware.h> +#include <asm/arch/emac_defs.h> + +#define MACH_TYPE_DA8XX_EVM 1781 + +DECLARE_GLOBAL_DATA_PTR; + +extern void timer_init(void); +extern int eth_hw_init(void); + +/* Works on Always On power domain only (no PD argument) */ +void lpsc_on(unsigned int id) +{ + dv_reg_p mdstat, mdctl, ptstat, ptcmd; + + if (id >= 64) + return; + + if(id < 32) { + mdstat = REG_P(PSC0_MDSTAT + (id * 4)); + mdctl = REG_P(PSC0_MDCTL + (id * 4)); + ptstat = REG_P(PSC0_PTSTAT); + ptcmd = REG_P(PSC0_PTCMD); + } else { + id -= 32; + mdstat = REG_P(PSC1_MDSTAT + (id * 4)); + mdctl = REG_P(PSC1_MDCTL + (id * 4)); + ptstat = REG_P(PSC1_PTSTAT); + ptcmd = REG_P(PSC1_PTCMD); + } + + while (*ptstat & 0x01) {;} + + if ((*mdstat & 0x1f) == 0x03) + return; /* Already on and enabled */ + + *mdctl |= 0x03; + + /* Special treatment for some modules as for sprue14 p.7.4.2 */ + /* TBD: Confirm if such cases exist for Primus */ + if (0) + *mdctl |= 0x200; + + *ptcmd = 0x01; + + while (*ptstat & 0x01) {;} + while ((*mdstat & 0x1f) != 0x03) {;} /* Probably an overkill... */ +} + +int board_init(void) +{ + + dv_reg_p intc; + + /*-------------------------------------------------------* + * Mask all IRQs by clearing the global enable and setting + * the enable clear for all the 90 interrupts. This code is + * also included in low level init. Including it here in case + * low level init is skipped. Not removing it from low level + * init in case some of the low level init code generates + * interrupts... Not expected... but you never know... + *-------------------------------------------------------*/ + +#ifndef CONFIG_USE_IRQ + intc = REG_P(INTC_GLB_EN); + intc[0] = 0; + + intc = REG_P(INTC_HINT_EN); + intc[0] = 0; + intc[1] = 0; + intc[2] = 0; + + intc = REG_P(INTC_EN_CLR0); + intc[0] = 0xFFFFFFFF; + intc[1] = 0xFFFFFFFF; + intc[2] = 0xFFFFFFFF; +#endif + + /* arch number of the board */ + gd->bd->bi_arch_number = MACH_TYPE_DA8XX_EVM; + + /* address of boot parameters */ + gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; + + /* setup the SUSPSRC for ARM to control emulation suspend */ + REG(SUSPSRC) &= ~( (1 << 27) /* Timer0 */ + | (1 << 21) /* SPI0 */ + | (1 << 20) /* UART2 */ + | (1 << 5) /* EMAC */ + | (1 << 16) /* I2C0 */ + ); + + /* Power on required peripherals + * ARM does not have acess by default to PSC0 and PSC1 + * assuming here that the DSP bootloader has set the IOPU + * such that PSC access is available to ARM + */ + lpsc_on(DAVINCI_LPSC_AEMIF); /* NAND, NOR */ + lpsc_on(DAVINCI_LPSC_SPI0); /* Serial Flash */ + lpsc_on(DAVINCI_LPSC_EMAC); /* image download */ + lpsc_on(DAVINCI_LPSC_UART2); /* console */ + lpsc_on(DAVINCI_LPSC_GPIO); + + /* Pin Muxing support */ + + /* write the kick registers to unlock the PINMUX registers */ + REG(KICK0) = 0x83e70b13; /* Kick0 unlock */ + REG(KICK1) = 0x95a4f1e0; /* Kick1 unlock */ + +#ifdef CONFIG_SPI_FLASH + /* SPI0 */ + REG(PINMUX7) &= 0x00000FFF; + REG(PINMUX7) |= 0x11111000; +#endif + +#ifdef CONFIG_DRIVER_TI_EMAC + /* RMII clock is sourced externally */ + REG(PINMUX9) &= 0xFF0FFFFF; + REG(PINMUX10) &= 0x0000000F; + REG(PINMUX10) |= 0x22222220; + REG(PINMUX11) &= 0xFFFFFF00; + REG(PINMUX11) |= 0x00000022; +#endif + + /* Async EMIF */ +#if defined(CFG_USE_NAND) || defined(CFG_USE_NOR) + REG(PINMUX13) &= 0x00FFFFFF; + REG(PINMUX13) |= 0x11000000; + REG(PINMUX14) = 0x11111111; + REG(PINMUX15) = 0x11111111; + REG(PINMUX16) = 0x11111111; + REG(PINMUX17) = 0x11111111; + REG(PINMUX18) = 0x11111111; + REG(PINMUX19) &= 0xFFFFFFF0; + REG(PINMUX19) |= 0x1; +#endif + + /* UART Muxing and enabling */ + REG(PINMUX8) &= 0x0FFFFFFF; + REG(PINMUX8) |= 0x20000000; + + REG(PINMUX9) &= 0xFFFFFFF0; + REG(PINMUX9) |= 0x00000002; + + REG(DAVINCI_UART2_BASE + 0x30) = 0xE001; + + /* I2C muxing */ + REG(PINMUX8) &= 0xFFF00FFF; + REG(PINMUX8) |= 0x00022000; + + /* write the kick registers to lock the PINMUX registers */ + REG(KICK0) = 0x0; /* Kick0 lock */ + REG(KICK1) = 0x0; /* Kick1 lock */ + + return(0); +} + +int misc_init_r (void) +{ + u_int8_t tmp[20], buf[10]; + int i; + + printf ("ARM Clock : %d Hz\n", clk_get(DAVINCI_ARM_CLKID)); + + /* Set Ethernet MAC address from EEPROM */ + if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0x7f00, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, 6)) { + printf("\nEEPROM @ 0x%02x read FAILED!!!\n", CONFIG_SYS_I2C_EEPROM_ADDR); + } else { + tmp[0] = 0xff; + for (i = 0; i < 6; i++) + tmp[0] &= buf[i]; + + if ((tmp[0] != 0xff) && (getenv("ethaddr") == NULL)) { + sprintf((char *)&tmp[0], "%02x:%02x:%02x:%02x:%02x:%02x", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + setenv("ethaddr", (char *)&tmp[0]); + } + } + + tmp[0] = 0x01; + tmp[1] = 0x23; + if(i2c_write(0x5f, 0, 0, tmp, 2)) { + printf("Ethernet switch start failed!\n"); + } + + if (!eth_hw_init()) { + printf("Error: Ethernet init failed!\n"); + } + + return(0); +} + +int dram_init(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + + return(0); +} diff --git a/board/da8xx/da8xx-evm/u-boot.lds b/board/da8xx/da8xx-evm/u-boot.lds new file mode 100644 index 0000000000..a4fcd1a9bb --- /dev/null +++ b/board/da8xx/da8xx-evm/u-boot.lds @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss (NOLOAD) : { *(.bss) } + _end = .; +} diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 85025daec7..cdb74bb256 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -549,6 +549,7 @@ int getenv_r (char *name, char *buf, unsigned len) #if ((defined(CONFIG_ENV_IS_IN_NVRAM) || defined(CONFIG_ENV_IS_IN_EEPROM) \ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_SF)) \ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))) \ && !defined(CONFIG_ENV_IS_NOWHERE)) int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) @@ -605,6 +606,7 @@ U_BOOT_CMD( #if ((defined(CONFIG_ENV_IS_IN_NVRAM) || defined(CONFIG_ENV_IS_IN_EEPROM) \ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_SF)) \ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))) \ && !defined(CONFIG_ENV_IS_NOWHERE)) U_BOOT_CMD( diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 8c0a7514df..5d6db2d283 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -29,6 +29,11 @@ static int do_spi_flash_probe(int argc, char *argv[]) if (argc < 2) goto usage; + if(flash) { + printf("SPI flash already probed\n"); + goto probe_done; + } + cs = simple_strtoul(argv[1], &endp, 0); if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) goto usage; @@ -63,6 +68,7 @@ static int do_spi_flash_probe(int argc, char *argv[]) spi_flash_free(flash); flash = new; +probe_done: printf("%u KiB %s at %u:%u is now current device\n", flash->size >> 10, flash->name, bus, cs); diff --git a/cpu/arm926ejs/da8xx/Makefile b/cpu/arm926ejs/da8xx/Makefile new file mode 100644 index 0000000000..49fa3111ef --- /dev/null +++ b/cpu/arm926ejs/da8xx/Makefile @@ -0,0 +1,49 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = timer.o ether.o nand.o clock.o i2c.o +SOBJS = lowlevel_init.o reset.o + +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm926ejs/da8xx/clock.c b/cpu/arm926ejs/da8xx/clock.c new file mode 100644 index 0000000000..7cb979bc00 --- /dev/null +++ b/cpu/arm926ejs/da8xx/clock.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> + * + * DA8xx clock module + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + */ + +#include <common.h> +#include <asm/arch/hardware.h> + +dv_reg_p sysdiv[9] = { + PLL0_DIV1, PLL0_DIV2, PLL0_DIV3, PLL0_DIV4, PLL0_DIV5, PLL0_DIV6, + PLL0_DIV7, PLL0_DIV8, PLL0_DIV9 }; + +int clk_get(unsigned int id) +{ + int pre_div = (REG(PLL0_PREDIV) & 0xff) + 1; + int pllm = REG(PLL0_PLLM) + 1; + int post_div = (REG(PLL0_POSTDIV) & 0xff) + 1; + int pll_out = CFG_OSCIN_FREQ; + + if(id == DAVINCI_AUXCLK_CLKID) + goto out; + + /* Lets keep this simple. Combining operations can result in + * unexpected approximations + */ + pll_out /= pre_div; + pll_out *= pllm; + + if(id == DAVINCI_PLLM_CLKID) + goto out; + + pll_out /= post_div; + + if(id == DAVINCI_PLLC_CLKID) + goto out; + + pll_out /= (REG(sysdiv[id - 1]) & 0xff) + 1; + +out: + return pll_out; +} diff --git a/cpu/arm926ejs/da8xx/ether.c b/cpu/arm926ejs/da8xx/ether.c new file mode 100644 index 0000000000..f128196bb9 --- /dev/null +++ b/cpu/arm926ejs/da8xx/ether.c @@ -0,0 +1,667 @@ +/* + * Ethernet driver for TI TMS320DM644x (DaVinci) chips. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright + * follows: + * + * ---------------------------------------------------------------------------- + * + * dm644x_emac.c + * + * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM + * + * Copyright (C) 2005 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + + * Modifications: + * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot. + * ver 1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors + * + */ +#include <common.h> +#include <command.h> +#include <net.h> +#include <miiphy.h> +#include <asm/arch/emac_defs.h> + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +unsigned int emac_dbg = 0; +#define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args) + +/* Internal static functions */ +static int dm644x_eth_hw_init (void); +static int dm644x_eth_open (void); +static int dm644x_eth_close (void); +static int dm644x_eth_send_packet (volatile void *packet, int length); +static int dm644x_eth_rcv_packet (void); +static void dm644x_eth_mdio_enable(void); + +static int gen_init_phy(int phy_addr); +static int gen_is_phy_connected(int phy_addr); +static int gen_get_link_speed(int phy_addr); +static int gen_auto_negotiate(int phy_addr); + +/* Wrappers exported to the U-Boot proper */ +int eth_hw_init(void) +{ + return(dm644x_eth_hw_init()); +} + +int eth_init(bd_t * bd) +{ + return(dm644x_eth_open()); +} + +void eth_halt(void) +{ + dm644x_eth_close(); +} + +int eth_send(volatile void *packet, int length) +{ + return(dm644x_eth_send_packet(packet, length)); +} + +int eth_rx(void) +{ + return(dm644x_eth_rcv_packet()); +} + +void eth_mdio_enable(void) +{ + dm644x_eth_mdio_enable(); +} +/* End of wrappers */ + +/* dm644x_eth_mac_addr[0] goes out on the wire first */ + +static u_int8_t dm644x_eth_mac_addr[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0x00 }; + +/* + * This function must be called before emac_open() if you want to override + * the default mac address. + */ +void dm644x_eth_set_mac_addr(const u_int8_t *addr) +{ + int i; + + for (i = 0; i < sizeof (dm644x_eth_mac_addr); i++) { + dm644x_eth_mac_addr[i] = addr[i]; + } +} + +/* EMAC Addresses */ +static volatile emac_regs *adap_emac = (emac_regs *)EMAC_BASE_ADDR; +static volatile ewrap_regs *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR; +static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR; + +/* EMAC descriptors */ +static volatile emac_desc *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE); +static volatile emac_desc *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE); +static volatile emac_desc *emac_rx_active_head = 0; +static volatile emac_desc *emac_rx_active_tail = 0; +static int emac_rx_queue_active = 0; + +/* Receive packet buffers */ +static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; + +/* PHY address for a discovered PHY (0xff - not found) */ +static volatile u_int8_t active_phy_addr = 0xff; + +static int no_phy_init (int phy_addr) { return(1); } +static int no_phy_is_connected (int phy_addr) { return(1); } +static int no_phy_get_link_speed (int phy_addr) { return(1); } +static int no_phy_auto_negotiate (int phy_addr) { return(1); } +phy_t phy = { + .init = no_phy_init, + .is_phy_connected = no_phy_is_connected, + .get_link_speed = no_phy_get_link_speed, + .auto_negotiate = no_phy_auto_negotiate +}; + +static void dm644x_eth_mdio_enable(void) +{ + u_int32_t clkdiv; + + clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; + + adap_mdio->CONTROL = (clkdiv & 0xff) | + MDIO_CONTROL_ENABLE | + MDIO_CONTROL_FAULT | + MDIO_CONTROL_FAULT_ENABLE; + + while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;} +} + +/* + * Tries to find an active connected PHY. Returns 1 if address if found. + * If no active PHY found returns 0. If more than one active PHY (switch) + * returns 2 + * Sets active_phy_addr variable when returns 1. + */ +static int dm644x_eth_phy_detect(void) +{ + u_int32_t phy_act_state; + int i; + + active_phy_addr = 0xff; + + if ((phy_act_state = adap_mdio->ALIVE) == 0) + return(0); /* No active PHYs */ + + debug_emac("dm644x_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state); + + for (i = 0; i < 32; i++) { + if (phy_act_state & (1 << i)) { + if (phy_act_state & ~(1 << i)) + return(2); /* More than one PHY */ + else { + active_phy_addr = i; + return(1); + } + } + } + + return(0); /* Just to make GCC happy */ +} + + +/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */ +int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) +{ + int tmp; + + while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} + + adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO | + MDIO_USERACCESS0_WRITE_READ | + ((reg_num & 0x1f) << 21) | + ((phy_addr & 0x1f) << 16); + + /* Wait for command to complete */ + while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;} + + if (tmp & MDIO_USERACCESS0_ACK) { + *data = tmp & 0xffff; + return(1); + } + + *data = -1; + return(0); +} + +/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */ +int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) +{ + + while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} + + adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO | + MDIO_USERACCESS0_WRITE_WRITE | + ((reg_num & 0x1f) << 21) | + ((phy_addr & 0x1f) << 16) | + (data & 0xffff); + + /* Wait for command to complete */ + while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} + + return(1); +} + +/* PHY functions for a generic PHY */ +static int gen_init_phy(int phy_addr) +{ + int ret = 1; + + if (gen_get_link_speed(phy_addr)) { + /* Try another time */ + ret = gen_get_link_speed(phy_addr); + } + + return(ret); +} + +static int gen_is_phy_connected(int phy_addr) +{ + u_int16_t dummy; + + return(dm644x_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy)); +} + +static int gen_get_link_speed(int phy_addr) +{ + u_int16_t tmp; + + if (dm644x_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04)) + return(1); + + return(0); +} + +static int gen_auto_negotiate(int phy_addr) +{ + u_int16_t tmp; + + if (!dm644x_eth_phy_read(phy_addr, PHY_BMCR, &tmp)) + return(0); + + /* Restart Auto_negotiation */ + tmp |= PHY_BMCR_AUTON; + dm644x_eth_phy_write(phy_addr, PHY_BMCR, tmp); + + /*check AutoNegotiate complete */ + udelay (10000); + if (!dm644x_eth_phy_read(phy_addr, PHY_BMSR, &tmp)) + return(0); + + if (!(tmp & PHY_BMSR_AUTN_COMP)) + return(0); + + return(gen_get_link_speed(phy_addr)); +} +/* End of generic PHY functions */ + + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +static int dm644x_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value) +{ + return(dm644x_eth_phy_read(addr, reg, value) ? 0 : 1); +} + +static int dm644x_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value) +{ + return(dm644x_eth_phy_write(addr, reg, value) ? 0 : 1); +} + +int dm644x_eth_miiphy_initialize(bd_t *bis) +{ + miiphy_register(phy.name, dm644x_mii_phy_read, dm644x_mii_phy_write); + + return(1); +} +#endif + +/* + * This function initializes the emac hardware. It does NOT initialize + * EMAC modules power or pin multiplexors, that is done by board_init() + * much earlier in bootup process. Returns 1 on success, 0 otherwise. + */ +static int dm644x_eth_hw_init(void) +{ + u_int32_t phy_id; + u_int16_t tmp; + int i, ret; + + /* The RMII clock can be sources internally through the SYSCLK7 + * or can come externally through a dedicated pin. This selection is + * controlled by PinMux9[21]. PinMux registers are off-limits for ARM. + * In short, we just assume there is a 50MHz RMII clock available. + */ + + dm644x_eth_mdio_enable(); + + for (i = 0; i < 256; i++) { + if (adap_mdio->ALIVE) + break; + udelay(1000); + } + + if (i >= 256) { + printf("No ETH PHY detected!!!\n"); + return(0); + } + + /* Find if a PHY is connected and get it's address */ + ret = dm644x_eth_phy_detect(); + + if (ret == 2) { + printf("More than one PHY detected.\n"); + return(1); + } else if(ret == 0) + return(0); + + /* Get PHY ID and initialize phy_ops for a detected PHY */ + if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) { + active_phy_addr = 0xff; + return(0); + } + + phy_id = (tmp << 16) & 0xffff0000; + + if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) { + active_phy_addr = 0xff; + return(0); + } + + phy_id |= tmp & 0x0000ffff; + + switch (phy_id) { + default: + sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr); + phy.init = gen_init_phy; + phy.is_phy_connected = gen_is_phy_connected; + phy.get_link_speed = gen_get_link_speed; + phy.auto_negotiate = gen_auto_negotiate; + } + + return(1); +} + + +/* Eth device open */ +static int dm644x_eth_open(void) +{ + dv_reg_p addr; + u_int32_t clkdiv, cnt; + volatile emac_desc *rx_desc; + int i; + + debug_emac("+ emac_open\n"); + + /* Reset EMAC module and disable interrupts in wrapper */ + adap_emac->SOFTRESET = 1; + while (adap_emac->SOFTRESET != 0) {;} + adap_ewrap->SOFTRESET = 1; + while (adap_ewrap->SOFTRESET != 0) {;} + + adap_ewrap->C0RXEN = adap_ewrap->C1RXEN = adap_ewrap->C2RXEN = 0; + adap_ewrap->C0TXEN = adap_ewrap->C1TXEN = adap_ewrap->C2TXEN = 0; + adap_ewrap->C0MISCEN = adap_ewrap->C1MISCEN = adap_ewrap->C2MISCEN = 0; + + rx_desc = emac_rx_desc; + + adap_emac->TXCONTROL = 0x01; + adap_emac->RXCONTROL = 0x01; + + /* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */ + /* Using channel 0 only - other channels are disabled */ + for (i = 0; i < 8; i++) { + adap_emac->MACINDEX = i; + adap_emac->MACADDRHI = + (dm644x_eth_mac_addr[3] << 24) | /* bits 23-16 */ + (dm644x_eth_mac_addr[2] << 16) | /* bits 31-24 */ + (dm644x_eth_mac_addr[1] << 8) | /* bits 39-32 */ + (dm644x_eth_mac_addr[0]); /* bits 47-40 */ + adap_emac->MACADDRLO = + (dm644x_eth_mac_addr[5] << 8) | /* bits 8-0*/ + (dm644x_eth_mac_addr[4]) | (1 << 19) | (1 << 20); /* bits 8-0 */ + } + + adap_emac->MACHASH1 = 0; + adap_emac->MACHASH2 = 0; + + /* Set source MAC address - REQUIRED for pause frames */ + adap_emac->MACSRCADDRHI = + (dm644x_eth_mac_addr[3] << 24) | /* bits 23-16 */ + (dm644x_eth_mac_addr[2] << 16) | /* bits 31-24 */ + (dm644x_eth_mac_addr[1] << 8) | /* bits 39-32 */ + (dm644x_eth_mac_addr[0]); /* bits 47-40 */ + adap_emac->MACSRCADDRLO = + (dm644x_eth_mac_addr[5] << 8) | /* bits 8-0 */ + (dm644x_eth_mac_addr[4]); /* bits 15-8 */ + + /* Set DMA 8 TX / 8 RX Head pointers to 0 */ + addr = &adap_emac->TX0HDP; + for(cnt = 0; cnt < 16; cnt++) + *addr++ = 0; + + addr = &adap_emac->TX0CP; + for(cnt = 0; cnt < 16; cnt++) + *addr++ = 0; + + /* Clear Statistics (do this before setting MacControl register) */ + addr = &adap_emac->RXGOODFRAMES; + for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++) + *addr++ = 0; + + /* No multicast addressing */ + adap_emac->MACHASH1 = 0; + adap_emac->MACHASH2 = 0; + + /* Create RX queue and set receive process in place */ + emac_rx_active_head = emac_rx_desc; + for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) { + rx_desc->next = (u_int32_t)(rx_desc + 1); + rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; + rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; + rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; + rx_desc++; + } + + /* Set the last descriptor's "next" parameter to 0 to end the RX desc list */ + rx_desc--; + rx_desc->next = 0; + emac_rx_active_tail = rx_desc; + emac_rx_queue_active = 1; + + /* Enable TX/RX */ + adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE; + adap_emac->RXBUFFEROFFSET = 0; + + /* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */ + adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN; + + /* Enable ch 0 only */ + adap_emac->RXUNICASTSET = 0x01; + + /* Enable MII interface and Full duplex mode */ + adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE) | EMAC_MACCONTROL_RMIISPEED_100; + + /* Init MDIO & get link state */ + clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; + adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT); + + if (!phy.get_link_speed(active_phy_addr)) + return(0); + + /* Start receive process */ + adap_emac->RX0HDP = (u_int32_t)emac_rx_desc; + + debug_emac("- emac_open\n"); + + return(1); +} + +/* EMAC Channel Teardown */ +static void dm644x_eth_ch_teardown(int ch) +{ + dv_reg dly = 0xff; + dv_reg cnt; + + debug_emac("+ emac_ch_teardown\n"); + + if (ch == EMAC_CH_TX) { + /* Init TX channel teardown */ + adap_emac->TXTEARDOWN = 1; + for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) { + /* Wait here for Tx teardown completion interrupt to occur + * Note: A task delay can be called here to pend rather than + * occupying CPU cycles - anyway it has been found that teardown + * takes very few cpu cycles and does not affect functionality */ + dly--; + udelay(1); + if (dly == 0) + break; + } + adap_emac->TX0CP = cnt; + adap_emac->TX0HDP = 0; + } else { + /* Init RX channel teardown */ + adap_emac->RXTEARDOWN = 1; + for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) { + /* Wait here for Rx teardown completion interrupt to occur + * Note: A task delay can be called here to pend rather than + * occupying CPU cycles - anyway it has been found that teardown + * takes very few cpu cycles and does not affect functionality */ + dly--; + udelay(1); + if (dly == 0) + break; + } + adap_emac->RX0CP = cnt; + adap_emac->RX0HDP = 0; + } + + debug_emac("- emac_ch_teardown\n"); +} + +/* Eth device close */ +static int dm644x_eth_close(void) +{ + debug_emac("+ emac_close\n"); + + dm644x_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */ + dm644x_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */ + + /* Reset EMAC module and disable interrupts in wrapper */ + adap_emac->SOFTRESET = 1; + adap_ewrap->SOFTRESET = 1; + + adap_ewrap->C0RXEN = adap_ewrap->C1RXEN = adap_ewrap->C2RXEN = 0; + adap_ewrap->C0TXEN = adap_ewrap->C1TXEN = adap_ewrap->C2TXEN = 0; + adap_ewrap->C0MISCEN = adap_ewrap->C1MISCEN = adap_ewrap->C2MISCEN = 0; + + debug_emac("- emac_close\n"); + return(1); +} + +static int tx_send_loop = 0; + +/* + * This function sends a single packet on the network and returns + * positive number (number of bytes transmitted) or negative for error + */ +static int dm644x_eth_send_packet(volatile void *packet, int length) +{ + int ret_status = -1; + tx_send_loop = 0; + + /* Return error if no link */ + if (!phy.get_link_speed(active_phy_addr)) + { + printf("WARN: emac_send_packet: No link\n"); + return (ret_status); + } + + /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */ + if (length < EMAC_MIN_ETHERNET_PKT_SIZE) + { + length = EMAC_MIN_ETHERNET_PKT_SIZE; + } + + /* Populate the TX descriptor */ + emac_tx_desc->next = 0; + emac_tx_desc->buffer = (u_int8_t *)packet; + emac_tx_desc->buff_off_len = (length & 0xffff); + emac_tx_desc->pkt_flag_len = ((length & 0xffff) | + EMAC_CPPI_SOP_BIT | + EMAC_CPPI_OWNERSHIP_BIT | + EMAC_CPPI_EOP_BIT); + /* Send the packet */ + adap_emac->TX0HDP = (unsigned int)emac_tx_desc; + + /* Wait for packet to complete or link down */ + while (1) { + if (!phy.get_link_speed(active_phy_addr)) { + dm644x_eth_ch_teardown(EMAC_CH_TX); + return (ret_status); + } + if (adap_emac->TXINTSTATRAW & 0x01) { + ret_status = length; + break; + } + tx_send_loop++; + } + + return(ret_status); +} + +/* + * This function handles receipt of a packet from the network + */ +static int dm644x_eth_rcv_packet(void) +{ + volatile emac_desc *rx_curr_desc; + volatile emac_desc *curr_desc; + volatile emac_desc *tail_desc; + int status, ret = -1; + + rx_curr_desc = emac_rx_active_head; + status = rx_curr_desc->pkt_flag_len; + if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) { + if (status & EMAC_CPPI_RX_ERROR_FRAME) { + /* Error in packet - discard it and requeue desc */ + printf("WARN: emac_rcv_pkt: Error in packet\n"); + } else { + NetReceive(rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff)); + ret = rx_curr_desc->buff_off_len & 0xffff; + } + + /* Ack received packet descriptor */ + adap_emac->RX0CP = (unsigned int)rx_curr_desc; + curr_desc = rx_curr_desc; + emac_rx_active_head = (volatile emac_desc *)rx_curr_desc->next; + + if (status & EMAC_CPPI_EOQ_BIT) { + if (emac_rx_active_head) { + adap_emac->RX0HDP = (unsigned int)emac_rx_active_head; + } else { + emac_rx_queue_active = 0; + printf("INFO:emac_rcv_packet: RX Queue not active\n"); + } + } + + /* Recycle RX descriptor */ + rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; + rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; + rx_curr_desc->next = 0; + + if (emac_rx_active_head == 0) { + printf("INFO: emac_rcv_pkt: active queue head = 0\n"); + emac_rx_active_head = curr_desc; + emac_rx_active_tail = curr_desc; + if (emac_rx_queue_active != 0) { + adap_emac->RX0HDP = (unsigned int)emac_rx_active_head; + printf("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n"); + emac_rx_queue_active = 1; + } + } else { + tail_desc = emac_rx_active_tail; + emac_rx_active_tail = curr_desc; + tail_desc->next = (unsigned int)curr_desc; + status = tail_desc->pkt_flag_len; + if (status & EMAC_CPPI_EOQ_BIT) { + adap_emac->RX0HDP = (unsigned int)curr_desc; + status &= ~EMAC_CPPI_EOQ_BIT; + tail_desc->pkt_flag_len = status; + } + } + return(ret); + } + return(0); +} + +#endif /* CONFIG_CMD_NET */ + +#endif /* CONFIG_DRIVER_TI_EMAC */ diff --git a/cpu/arm926ejs/da8xx/i2c.c b/cpu/arm926ejs/da8xx/i2c.c new file mode 100644 index 0000000000..7b978a855f --- /dev/null +++ b/cpu/arm926ejs/da8xx/i2c.c @@ -0,0 +1,356 @@ +/* + * TI DaVinci (TMS320DM644x) I2C driver. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * -------------------------------------------------------- + * + * 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_DRIVER_DAVINCI_I2C + +#include <i2c.h> +#include <asm/arch/hardware.h> +#include <asm/arch/i2c_defs.h> + +#define CHECK_NACK() \ + do {\ + if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ + REG(I2C_CON) = 0;\ + return(1);\ + }\ + } while (0) + + +static int wait_for_bus(void) +{ + int stat, timeout; + + REG(I2C_STAT) = 0xffff; + + for (timeout = 0; timeout < 10; timeout++) { + if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) { + REG(I2C_STAT) = 0xffff; + return(0); + } + + REG(I2C_STAT) = stat; + udelay(50000); + } + + REG(I2C_STAT) = 0xffff; + return(1); +} + + +static int poll_i2c_irq(int mask) +{ + int stat, timeout; + + for (timeout = 0; timeout < 10; timeout++) { + udelay(1000); + stat = REG(I2C_STAT); + if (stat & mask) { + return(stat); + } + } + + REG(I2C_STAT) = 0xffff; + return(stat | I2C_TIMEOUT); +} + + +void flush_rx(void) +{ + int dummy; + + while (1) { + if (!(REG(I2C_STAT) & I2C_STAT_RRDY)) + break; + + dummy = REG(I2C_DRR); + REG(I2C_STAT) = I2C_STAT_RRDY; + udelay(1000); + } +} + + +void i2c_init(int speed, int slaveadd) +{ + u_int32_t div, psc; + + if (REG(I2C_CON) & I2C_CON_EN) { + REG(I2C_CON) = 0; + udelay (50000); + } + + /* Get 1MHz into I2C internal */ + psc = CONFIG_SYS_HZ_CLOCK/1000000; + + div = CONFIG_SYS_HZ_CLOCK / (psc * speed); /* SCLL + SCLH */ + + REG(I2C_PSC) = psc - 1; /* 27MHz / (2 + 1) = 9MHz */ + REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */ + REG(I2C_SCLH) = div - REG(I2C_SCLL); + + REG(I2C_OA) = slaveadd; + REG(I2C_CNT) = 0; + + /* Interrupts must be enabled or I2C module won't work */ + REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | + I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; + + /* Now enable I2C controller (get it out of reset) */ + REG(I2C_CON) = I2C_CON_EN; + + udelay(1000); +} + + +int i2c_probe(u_int8_t chip) +{ + int rc = 1; + + if (chip == REG(I2C_OA)) { + return(rc); + } + + REG(I2C_CON) = 0; + if (wait_for_bus()) {return(1);} + + /* try to read one byte from current (or only) address */ + REG(I2C_CNT) = 1; + REG(I2C_SA) = chip; + REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP | I2C_CON_FREE); + udelay (50000); + + if (!(REG(I2C_STAT) & I2C_STAT_NACK)) { + rc = 0; + flush_rx(); + REG(I2C_STAT) = 0xffff; + } else { + REG(I2C_STAT) = 0xffff; + REG(I2C_CON) |= I2C_CON_STP; + udelay(20000); + if (wait_for_bus()) {return(1);} + } + + flush_rx(); + REG(I2C_STAT) = 0xffff; + REG(I2C_CNT) = 0; + return(rc); +} + + +int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) +{ + u_int32_t tmp; + int i; + + if ((alen < 0) || (alen > 2)) { + printf("%s(): bogus address length %x\n", __FUNCTION__, alen); + return(1); + } + + if (wait_for_bus()) {return(1);} + + if (alen != 0) { + /* Start address phase */ + tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | + I2C_CON_FREE; + REG(I2C_CNT) = alen; + REG(I2C_SA) = chip; + REG(I2C_CON) = tmp; + + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + + CHECK_NACK(); + + switch (alen) { + case 2: + /* Send address MSByte */ + if (tmp & I2C_STAT_XRDY) { + REG(I2C_DXR) = (addr >> 8) & 0xff; + } else { + REG(I2C_CON) = 0; + return(1); + } + + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + + CHECK_NACK(); + /* No break, fall through */ + case 1: + /* Send address LSByte */ + if (tmp & I2C_STAT_XRDY) { + REG(I2C_DXR) = addr & 0xff; + } else { + REG(I2C_CON) = 0; + return(1); + } + + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); + + CHECK_NACK(); + + if (!(tmp & I2C_STAT_ARDY)) { + REG(I2C_CON) = 0; + return(1); + } + } + } + + /* Address phase is over, now read 'len' bytes and stop */ + tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP | I2C_CON_FREE; + REG(I2C_CNT) = len & 0xffff; + REG(I2C_SA) = chip; + REG(I2C_CON) = tmp; + + for (i = 0; i < len; i++) { + tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); + + CHECK_NACK(); + + if (tmp & I2C_STAT_RRDY) { + buf[i] = REG(I2C_DRR); + } else { + REG(I2C_CON) = 0; + return(1); + } + } + + tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); + + CHECK_NACK(); + + if (!(tmp & I2C_STAT_SCD)) { + REG(I2C_CON) = 0; + return(1); + } + + flush_rx(); + REG(I2C_STAT) = 0xffff; + REG(I2C_CNT) = 0; + REG(I2C_CON) = 0; + + return(0); +} + + +int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) +{ + u_int32_t tmp; + int i; + + if ((alen < 0) || (alen > 2)) { + printf("%s(): bogus address length %x\n", __FUNCTION__, alen); + return(1); + } + if (len < 0) { + printf("%s(): bogus length %x\n", __FUNCTION__, len); + return(1); + } + + if (wait_for_bus()) {return(1);} + + /* Start address phase */ + tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; + REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; + REG(I2C_SA) = chip; + REG(I2C_CON) = tmp; + + switch (alen) { + case 2: + /* Send address MSByte */ + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + + CHECK_NACK(); + + if (tmp & I2C_STAT_XRDY) { + REG(I2C_DXR) = (addr >> 8) & 0xff; + } else { + REG(I2C_CON) = 0; + return(1); + } + /* No break, fall through */ + case 1: + /* Send address LSByte */ + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + + CHECK_NACK(); + + if (tmp & I2C_STAT_XRDY) { + REG(I2C_DXR) = addr & 0xff; + } else { + REG(I2C_CON) = 0; + return(1); + } + } + + for (i = 0; i < len; i++) { + tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + + CHECK_NACK(); + + if (tmp & I2C_STAT_XRDY) { + REG(I2C_DXR) = buf[i]; + } else { + return(1); + } + } + + tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); + + CHECK_NACK(); + + if (!(tmp & I2C_STAT_SCD)) { + REG(I2C_CON) = 0; + return(1); + } + + flush_rx(); + REG(I2C_STAT) = 0xffff; + REG(I2C_CNT) = 0; + REG(I2C_CON) = 0; + + return(0); +} + +#if 0 +u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg) +{ + u_int8_t tmp; + + i2c_read(chip, reg, 1, &tmp, 1); + return(tmp); +} + + +void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val) +{ + u_int8_t tmp; + + i2c_write(chip, reg, 1, &tmp, 1); +} +#endif /* if 0 */ + +#endif /* CONFIG_DRIVER_DAVINCI_I2C */ diff --git a/cpu/arm926ejs/da8xx/lowlevel_init.S b/cpu/arm926ejs/da8xx/lowlevel_init.S new file mode 100644 index 0000000000..c36993e16e --- /dev/null +++ b/cpu/arm926ejs/da8xx/lowlevel_init.S @@ -0,0 +1,504 @@ +/* + * Low-level board setup code for TI DA8xx SoC based boards. + * + * Copyright (C) 2008 Texas Instruments, Inc <www.ti.com> + * Sekhar Nori <nsekhar@ti.com> + * + * Based on TI DaVinci low level init code. Original copyrights follow. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Partially based on TI sources, original copyrights follow: + */ + +/* + * Board specific setup info + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004 + * + * Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004 + * See file CREDITS for list of people who contributed to this + * project. + * + * Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005 + * See file CREDITS for list of people who contributed to this + * project. + * + * Modified for DV-EVM board by Swaminathan S, Nov 2005 + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <asm/arch/hardware.h> + +.globl lowlevel_init +lowlevel_init: + + nop + nop + nop + nop + + /* + * Call board-specific lowlevel init. + * That MUST be present and THAT returns + * back to arch calling code with "mov pc, lr." + */ + b dv_board_init + +#ifndef CONFIG_USE_IRQ + /*-------------------------------------------------------* + * Mask all IRQs by clearing the global enable and setting + * the enable clear for all the 90 interrupts. + *-------------------------------------------------------*/ + mov r1, $0 + ldr r0, INTC_GLB_EN_ADDR + str r1, [r0] + + ldr r0, INTC_HINT_EN_ADDR + str r1, [r0] + add r0, r0, $4 + str r1, [r0] + add r0, r0, $4 + str r1, [r0] + + mvn r1, r1 + ldr r0, INTC_EN_CLR0_ADDR + str r1, [r0] + add r0, r0, $4 + str r1, [r0] + add r0, r0, $4 + str r1, [r0] +#endif + + /*------------------------------------------------------* + * PLL0 Initialization - works only in non-secure devices + *------------------------------------------------------*/ + + /* TODO: Write the kick values and the PLL master lock bits */ + + /* Select OSCIN in clockmode bit in PLLCTL register. This is the only + * clock mode supported on DA8xx + */ + ldr r6, PLL0_PLLCTL_ADDR + ldr r7, PLL_CLKSRC_MASK + ldr r8, [r6] + and r8, r8, r7 + str r8, [r6] + + /* Clear the PLLENSRC bit in PLLCTL */ + ldr r7, PLL_ENSRC_MASK + and r8, r8, r7 + str r8, [r6] + + /* Bypass the PLL */ + ldr r7, PLL_BYPASS_MASK + and r8, r8, r7 + str r8, [r6] + + /* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */ + mov r10, $0x20 +WaitPLL0Loop: + subs r10, r10, $1 + bne WaitPLL0Loop + + /* Reset the PLL */ + ldr r7, PLL_RESET_MASK + and r8, r8, r7 + str r8, [r6] + + /* disable PLL output */ + mov r7, $0x10 + orr r8, r8, r7 + str r8, [r6] + + /* Power up the PLL */ + ldr r7, PLL_PWRUP_MASK + and r8, r8, r7 + str r8, [r6] + + /* Enable the PLL from Disable Mode */ + ldr r7, PLL_DISABLE_ENABLE_MASK + and r8, r8, r7 + str r8, [r6] + + /* Wait for the PLL stabilization time - 150us assumed */ + mov r10, $0xE10 +PLLStableLoop: + subs r10, r10, $1 + bne PLLStableLoop + + /* Program the PLL Multiplier */ + ldr r6, PLL0_PLLM_ADDR + mov r2, $0x18 /* 24 * 25 = 600MHz*/ + str r2, [r6] + + /* Program the POSTDIV Value */ + ldr r6, PLL0_POSTDIV_ADDR + mov r3, $0x01 + mov r3, r3, lsl $15 + orr r3, r3, $0x01 + str r3, [r6] + + /* Program the SYSCLKx dividedrs */ + + /* Following defaults are good: + * SYSCLK1 = /1 => 300MHz GEM + * SYSCLK2 = /2 => 150MHz EDMA, MMC/SD, UART1/2, SPI1 + * SYSCLK3 = /3 => 100MHz Possible EMIF2.5 + * SYSCLK4 = /4 => 75MHz INTC, PSC, EMAC, USB 1.1, I2C1 + * SYSCLK5 = /3 => 100MHz Possible EMIF3.0 (use DIV4p5) + * SYSCLK6 = /1 => 300MHz ARM + * SYSCLK7 = /6 => 50MHz RMII Ref Clk + * SYSCLK8 = /6 => 50MHz Dont use + * SYSCLK9 = /6 => 50MHz Dont use + * AUXCLK FIXED => 24Mhz Timer 0/1, 12C0, McASP AuxClk + */ + + /* Wait for PLL to Reset Properly - 128 OSCIN cycles*/ + mov r10, $128 +ResetPPL2Loop: + subs r10, r10, $1 + bne ResetPPL2Loop + + /* Bring PLL out of Reset */ + ldr r6, PLL0_PLLCTL_ADDR + ldr r8, [r6] + orr r8, r8, $0x08 + str r8, [r6] + + /* Wait for PLL to Lock */ + ldr r10, PLL_LOCK_COUNT +PLL0Lock: + subs r10, r10, $1 + bne PLL0Lock + + /* Enable the PLL */ + ldr r6, PLL0_PLLCTL_ADDR + ldr r8, [r6] + orr r8, r8, $0x01 + str r8, [r6] + + /*------------------------------------------------------* + * Setup the pinmux for DDR2 * + *------------------------------------------------------*/ + + ldr r0, PINMUX1_ADDR + ldr r1, PINMUX1_VAL + str r1, [r0] + + ldr r0, PINMUX2_ADDR + ldr r1, PINMUX2_VAL + str r1, [r0] + + ldr r0, PINMUX5_ADDR + ldr r1, PINMUX5_VAL + str r1, [r0] + + ldr r0, PINMUX6_ADDR + ldr r1, PINMUX6_VAL + str r1, [r0] + + ldr r8, PINMUX7_FLAG_CLEAR + ldr r7, PINMUX7_VAL + ldr r0, PINMUX7_ADDR + ldr r1, [r0] + and r1, r1, r8 + orr r1, r1, r7 + str r1, [r0] + + + /*------------------------------------------------------* + * Get the EMIF3 out of reset * + *------------------------------------------------------*/ + + /* Shut down the DDR2 LPSC Module */ + ldr r8, PSC_FLAG_CLEAR + ldr r6, MDCTL_EMIF3 + ldr r7, [r6] + and r7, r7, r8 + orr r7, r7, $0x03 + str r7, [r6] + + /* Enable the Power Domain Transition Command */ + ldr r6, PSC1_PTCMD_ADDR + ldr r7, [r6] + orr r7, r7, $0x01 + str r7, [r6] + + /* Check for Transition Complete(PTSTAT) */ +checkStatClkStop0: + ldr r6, PSC1_PTSTAT_ADDR + ldr r7, [r6] + ands r7, r7, $0x01 + bne checkStatClkStop0 + + /* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkStop0: + ldr r6, MDSTAT_EMIF3 + ldr r7, [r6] + and r7, r7, $0x1f + cmp r7, $0x03 + bne checkDDRStatClkStop0 + + /*------------------------------------------------------* + * Put the EMIF3 in reset * + *------------------------------------------------------*/ + + /* Shut down the DDR2 LPSC Module */ + ldr r8, PSC_FLAG_CLEAR + ldr r6, MDCTL_EMIF3 + ldr r7, [r6] + and r7, r7, r8 + orr r7, r7, $0x01 + str r7, [r6] + + /* Enable the Power Domain Transition Command */ + ldr r6, PSC1_PTCMD_ADDR + ldr r7, [r6] + orr r7, r7, $0x01 + str r7, [r6] + + /* Check for Transition Complete(PTSTAT) */ +checkStatClkStop1: + ldr r6, PSC1_PTSTAT_ADDR + ldr r7, [r6] + ands r7, r7, $0x01 + bne checkStatClkStop1 + + /* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkStop1: + ldr r6, MDSTAT_EMIF3 + ldr r7, [r6] + and r7, r7, $0x1f + cmp r7, $0x01 + bne checkDDRStatClkStop1 + + nop + nop + + /*------------------------------------------------------* + * Get the EMIF3 out of reset * + *------------------------------------------------------*/ + + /* Shut down the DDR2 LPSC Module */ + ldr r8, PSC_FLAG_CLEAR + ldr r6, MDCTL_EMIF3 + ldr r7, [r6] + and r7, r7, r8 + orr r7, r7, $0x03 + str r7, [r6] + + /* Enable the Power Domain Transition Command */ + ldr r6, PSC1_PTCMD_ADDR + ldr r7, [r6] + orr r7, r7, $0x01 + str r7, [r6] + + /* Check for Transition Complete(PTSTAT) */ +checkStatClkStop2: + ldr r6, PSC1_PTSTAT_ADDR + ldr r7, [r6] + ands r7, r7, $0x01 + bne checkStatClkStop2 + + /* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkStop2: + ldr r6, MDSTAT_EMIF3 + ldr r7, [r6] + and r7, r7, $0x1f + cmp r7, $0x03 + bne checkDDRStatClkStop2 + + nop + nop + + /*-----------------------------------------------------* + * Wait before programing the SDRAM timimg values * + *-----------------------------------------------------*/ + + ldr r10, EMIF3_TIMING_WAIT_VAL +emif3TimingWait: + sub r10, r10, $0x1 + cmp r10, $0x0 + bne emif3TimingWait + + /*------------------------------------------------------* + * Program EMIF3 MMRs for 133MHz SDRAM Setting * + *------------------------------------------------------*/ + + /* Program SDRAM Bank Config Register */ + ldr r6, SDCFG + ldr r7, SDCFG_VAL + str r7, [r6] + + /* Program SDRAM TIM-0 Config Register */ + ldr r6, SDTIM0 + ldr r7, SDTIM0_VAL_162MHz + str r7, [r6] + + /* Program SDRAM TIM-1 Config Register */ + ldr r6, SDTIM1 + ldr r7, SDTIM1_VAL_162MHz + str r7, [r6] + + /* Program the SDRAM Bank Config Control Register */ + ldr r10, MASK_VAL + ldr r8, SDCFG + ldr r9, SDCFG_VAL + and r9, r9, r10 + str r9, [r8] + + /* Program SDRAM SDREF Config Register */ + ldr r6, SDREF + ldr r7, SDREF_VAL + str r7, [r6] + + /* Issue a Dummy DDR2 read/write */ + ldr r8, DDR2_START_ADDR + ldr r7, DUMMY_VAL + str r7, [r8] + ldr r7, [r8] + + /* DDR Writes and Reads */ + ldr r6, CFGTEST + mov r3, $0x01 + str r3, [r6] + + nop + nop + nop + nop + + /* + * Call board-specific lowlevel init. + * That MUST be present and THAT returns + * back to arch calling code with "mov pc, lr." + */ + b dv_board_init + +.ltorg + +PINMUX1_ADDR: + .word PINMUX1 +PINMUX2_ADDR: + .word PINMUX2 +PINMUX5_ADDR: + .word PINMUX5 +PINMUX6_ADDR: + .word PINMUX6 +PINMUX7_ADDR: + .word PINMUX7 +PINMUX1_VAL: + .word 0x11111111 +PINMUX2_VAL: + .word 0x01111111 +PINMUX5_VAL: + .word 0x11111110 +PINMUX6_VAL: + .word 0x11111111 +PINMUX7_FLAG_CLEAR: + .word 0xFFFFF000 +PINMUX7_VAL: + .word 0x111 + + +MDCTL_EMIF3: + .word PSC1_MDCTL + 4 * 6 +MDSTAT_EMIF3: + .word PSC1_MDSTAT + 4 * 6 + +PSC1_PTCMD_ADDR: + .word PSC1_PTCMD +PSC1_PTSTAT_ADDR: + .word PSC1_PTSTAT + +INTC_GLB_EN_ADDR: + .word INTC_GLB_EN +INTC_EN_CLR0_ADDR: + .word INTC_EN_CLR0 +INTC_HINT_EN_ADDR: + .word INTC_HINT_EN + +PSC_FLAG_CLEAR: + .word 0xffffffe0 +PSC_GEM_FLAG_CLEAR: + .word 0xfffffeff + +/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */ +SDREF: + .word DAVINCI_DDR_EMIF_CTRL_BASE + 0xc +SDREF_VAL: + .word 0x000005c3 +SDCFG: + .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x8 +SDCFG_VAL: +#ifdef SDRAM_4BANKS_10COLS + .word 0x00178622 +#elif defined SDRAM_8BANKS_10COLS + .word 0x00178632 +#else +#error "Unknown SDRAM configuration!!!" +#endif +SDTIM0: + .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x10 +SDTIM0_VAL_162MHz: + .word 0x28923211 +SDTIM1: + .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x14 +SDTIM1_VAL_162MHz: + .word 0x0016c722 +CFGTEST: + .word DAVINCI_DDR_EMIF_DATA_BASE + 0x10000 +MASK_VAL: + .word 0x00000fff +EMIF3_TIMING_WAIT_VAL: + .word 990000 + +PLL_CLKSRC_MASK: + .word 0xfffffeff /* Mask the Clock Mode bit */ +PLL_ENSRC_MASK: + .word 0xffffffdf /* Select the PLLEN source */ +PLL_BYPASS_MASK: + .word 0xfffffffe /* Put the PLL in BYPASS */ +PLL_RESET_MASK: + .word 0xfffffff7 /* Put the PLL in Reset Mode */ +PLL_PWRUP_MASK: + .word 0xfffffffd /* PLL Power up Mask Bit */ +PLL_DISABLE_ENABLE_MASK: + .word 0xffffffef /* Enable the PLL from Disable */ +PLL_LOCK_COUNT: + .word 2000 + +/* PLL0 MMRs */ +PLL0_PLLCTL_ADDR: + .word PLL0_PLLCTL +PLL0_PLLM_ADDR: + .word PLL0_PLLM +PLL0_POSTDIV_ADDR: + .word PLL0_POSTDIV + +DDR2_START_ADDR: + .word 0xc0000000 +DUMMY_VAL: + .word 0xa55aa55a diff --git a/cpu/arm926ejs/da8xx/nand.c b/cpu/arm926ejs/da8xx/nand.c new file mode 100644 index 0000000000..014e2b0c11 --- /dev/null +++ b/cpu/arm926ejs/da8xx/nand.c @@ -0,0 +1,475 @@ +/* + * NAND driver for TI DaVinci based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Based on Linux DaVinci NAND driver by TI. Original copyright follows: + */ + +/* + * + * linux/drivers/mtd/nand/nand_davinci.c + * + * NAND Flash Driver + * + * Copyright (C) 2006 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + * + * Overview: + * This is a device driver for the NAND flash device found on the + * DaVinci board which utilizes the Samsung k9k2g08 part. + * + Modifications: + ver. 1.0: Feb 2005, Vinod/Sudhakar + - + * + */ + +#include <common.h> +#include <asm/io.h> + +#ifdef CONFIG_SYS_USE_NAND +#if !defined(CONFIG_NAND_LEGACY) + +#include <nand.h> +#include <asm/arch/nand_defs.h> +#include <asm/arch/emif_defs.h> + +extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE]; + +static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W; + + IO_ADDR_W &= ~(MASK_ALE|MASK_CLE); + + if (ctrl & NAND_CTRL_CHANGE) { + if ( ctrl & NAND_CLE ) + IO_ADDR_W |= MASK_CLE; + if ( ctrl & NAND_ALE ) + IO_ADDR_W |= MASK_ALE; + this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; + } + + if (cmd != NAND_CMD_NONE) + writeb(cmd, this->IO_ADDR_W); +} + +/* Set WP on deselect, write enable on select */ +static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) +{ +#define GPIO_SET_DATA01 0x01c67018 +#define GPIO_CLR_DATA01 0x01c6701c +#define GPIO_NAND_WP (1 << 4) +#ifdef SONATA_BOARD_GPIOWP + if (chip < 0) { + REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP; + } else { + REG(GPIO_SET_DATA01) |= GPIO_NAND_WP; + } +#endif +} + +#ifdef CONFIG_SYS_NAND_HW_ECC +#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC +/* Linux-compatible ECC uses MTD defaults. */ +/* These layouts are not compatible with Linux or RBL/UBL. */ +#ifdef CONFIG_SYS_NAND_LARGEPAGE +static struct nand_ecclayout davinci_nand_ecclayout = { + .eccbytes = 12, + .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, + .oobfree = { + {.offset = 2, .length = 6}, + {.offset = 12, .length = 12}, + {.offset = 28, .length = 12}, + {.offset = 44, .length = 12}, + {.offset = 60, .length = 4} + } +}; +#elif defined(CONFIG_SYS_NAND_SMALLPAGE) +static struct nand_ecclayout davinci_nand_ecclayout = { + .eccbytes = 3, + .eccpos = {0, 1, 2}, + .oobfree = { + {.offset = 6, .length = 2}, + {.offset = 8, .length = 8} + } +}; +#else +#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" +#endif +#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ + +static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) +{ + emifregs emif_addr; + int dummy; + + emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; + + dummy = emif_addr->NANDF1ECC; + dummy = emif_addr->NANDF2ECC; + dummy = emif_addr->NANDF3ECC; + dummy = emif_addr->NANDF4ECC; + + emif_addr->NANDFCR |= (1 << 8); +} + +static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) +{ + u_int32_t ecc = 0; + emifregs emif_base_addr; + + emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; + + if (region == 1) + ecc = emif_base_addr->NANDF1ECC; + else if (region == 2) + ecc = emif_base_addr->NANDF2ECC; + else if (region == 3) + ecc = emif_base_addr->NANDF3ECC; + else if (region == 4) + ecc = emif_base_addr->NANDF4ECC; + + return(ecc); +} + +static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +{ + u_int32_t tmp; +#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC + /* + * This is not how you should read ECCs on large page Davinci devices. + * The region parameter gets you ECCs for flash chips on different chip + * selects, not the 4x512 byte pages in a 2048 byte page. + * + * Preserved for backwards compatibility though. + */ + + int region, n; + struct nand_chip *this = mtd->priv; + + n = (this->ecc.size/512); + + region = 1; + while (n--) { + tmp = nand_davinci_readecc(mtd, region); + *ecc_code++ = tmp; + *ecc_code++ = tmp >> 16; + *ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0); + region++; + } +#else + const int region = 1; + + tmp = nand_davinci_readecc(mtd, region); + + /* Squeeze 4 bytes ECC into 3 bytes by removing RESERVED bits + * and shifting. RESERVED bits are 31 to 28 and 15 to 12. */ + tmp = (tmp & 0x00000fff) | ((tmp & 0x0fff0000) >> 4); + + /* Invert so that erased block ECC is correct */ + tmp = ~tmp; + + *ecc_code++ = tmp; + *ecc_code++ = tmp >> 8; + *ecc_code++ = tmp >> 16; +#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ + return(0); +} + +#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC +static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf) +{ + u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8); + + ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp)); + ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp)); + ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp)); +} + +static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data) +{ + u_int32_t i; + u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8]; + u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8]; + u_int8_t ecc_bit[24]; + u_int8_t ecc_sum = 0; + u_int8_t find_bit = 0; + u_int32_t find_byte = 0; + int is_ecc_ff; + + is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff)); + + nand_davinci_gen_true_ecc(ecc_nand); + nand_davinci_gen_true_ecc(ecc_calc); + + for (i = 0; i <= 2; i++) { + *(ecc_nand + i) = ~(*(ecc_nand + i)); + *(ecc_calc + i) = ~(*(ecc_calc + i)); + } + + for (i = 0; i < 8; i++) { + tmp0_bit[i] = *ecc_nand % 2; + *ecc_nand = *ecc_nand / 2; + } + + for (i = 0; i < 8; i++) { + tmp1_bit[i] = *(ecc_nand + 1) % 2; + *(ecc_nand + 1) = *(ecc_nand + 1) / 2; + } + + for (i = 0; i < 8; i++) { + tmp2_bit[i] = *(ecc_nand + 2) % 2; + *(ecc_nand + 2) = *(ecc_nand + 2) / 2; + } + + for (i = 0; i < 8; i++) { + comp0_bit[i] = *ecc_calc % 2; + *ecc_calc = *ecc_calc / 2; + } + + for (i = 0; i < 8; i++) { + comp1_bit[i] = *(ecc_calc + 1) % 2; + *(ecc_calc + 1) = *(ecc_calc + 1) / 2; + } + + for (i = 0; i < 8; i++) { + comp2_bit[i] = *(ecc_calc + 2) % 2; + *(ecc_calc + 2) = *(ecc_calc + 2) / 2; + } + + for (i = 0; i< 6; i++) + ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2]; + + for (i = 0; i < 8; i++) + ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i]; + + for (i = 0; i < 8; i++) + ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i]; + + ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0]; + ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1]; + + for (i = 0; i < 24; i++) + ecc_sum += ecc_bit[i]; + + switch (ecc_sum) { + case 0: + /* Not reached because this function is not called if + ECC values are equal */ + return 0; + case 1: + /* Uncorrectable error */ + MTDDEBUG (MTD_DEBUG_LEVEL0, + "ECC UNCORRECTED_ERROR 1\n"); + return(-1); + case 12: + /* Correctable error */ + find_byte = (ecc_bit[23] << 8) + + (ecc_bit[21] << 7) + + (ecc_bit[19] << 6) + + (ecc_bit[17] << 5) + + (ecc_bit[15] << 4) + + (ecc_bit[13] << 3) + + (ecc_bit[11] << 2) + + (ecc_bit[9] << 1) + + ecc_bit[7]; + + find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; + + MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC " + "error at offset: %d, bit: %d\n", + find_byte, find_bit); + + page_data[find_byte] ^= (1 << find_bit); + + return(0); + default: + if (is_ecc_ff) { + if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0) + return(0); + } + MTDDEBUG (MTD_DEBUG_LEVEL0, + "UNCORRECTED_ERROR default\n"); + return(-1); + } +} +#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ + +static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) +{ + struct nand_chip *this = mtd->priv; +#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC + int block_count = 0, i, rc; + + block_count = (this->ecc.size/512); + for (i = 0; i < block_count; i++) { + if (memcmp(read_ecc, calc_ecc, 3) != 0) { + rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat); + if (rc < 0) { + return(rc); + } + } + read_ecc += 3; + calc_ecc += 3; + dat += 512; + } +#else + u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) | + (read_ecc[2] << 16); + u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) | + (calc_ecc[2] << 16); + u_int32_t diff = ecc_calc ^ ecc_nand; + + if (diff) { + if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) { + /* Correctable error */ + if ((diff >> (12 + 3)) < this->ecc.size) { + uint8_t find_bit = 1 << ((diff >> 12) & 7); + uint32_t find_byte = diff >> (12 + 3); + + dat[find_byte] ^= find_bit; + MTDDEBUG(MTD_DEBUG_LEVEL0, "Correcting single " + "bit ECC error at offset: %d, bit: " + "%d\n", find_byte, find_bit); + return 1; + } else { + return -1; + } + } else if (!(diff & (diff - 1))) { + /* Single bit ECC error in the ECC itself, + nothing to fix */ + MTDDEBUG(MTD_DEBUG_LEVEL0, "Single bit ECC error in " + "ECC.\n"); + return 1; + } else { + /* Uncorrectable error */ + MTDDEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n"); + return -1; + } + } +#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ + return(0); +} +#endif /* CONFIG_SYS_NAND_HW_ECC */ + +static int nand_davinci_dev_ready(struct mtd_info *mtd) +{ + emifregs emif_addr; + + emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; + + return(emif_addr->NANDFSR & 0x1); +} + +static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this) +{ + while(!nand_davinci_dev_ready(mtd)) {;} + *NAND_CE0CLE = NAND_STATUS; + return(*NAND_CE0DATA); +} + +static void nand_flash_init(void) +{ + u_int32_t acfg1 = 0x3ffffffc; + u_int32_t acfg2 = 0x3ffffffc; + u_int32_t acfg3 = 0x3ffffffc; + u_int32_t acfg4 = 0x3ffffffc; + emifregs emif_regs; + + /*------------------------------------------------------------------* + * NAND FLASH CHIP TIMEOUT @ 459 MHz * + * * + * AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz * + * AEMIF.CLK period = 1/76.5 MHz = 13.1 ns * + * * + *------------------------------------------------------------------*/ + acfg1 = 0 + | (0 << 31 ) /* selectStrobe */ + | (0 << 30 ) /* extWait */ + | (1 << 26 ) /* writeSetup 10 ns */ + | (3 << 20 ) /* writeStrobe 40 ns */ + | (1 << 17 ) /* writeHold 10 ns */ + | (1 << 13 ) /* readSetup 10 ns */ + | (5 << 7 ) /* readStrobe 60 ns */ + | (1 << 4 ) /* readHold 10 ns */ + | (3 << 2 ) /* turnAround ?? ns */ + | (0 << 0 ) /* asyncSize 8-bit bus */ + ; + + emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; + + emif_regs->AWCCR |= 0x10000000; + emif_regs->AB1CR = acfg1; /* 0x08244128 */; + emif_regs->AB2CR = acfg2; + emif_regs->AB3CR = acfg3; + emif_regs->AB4CR = acfg4; + emif_regs->NANDFCR = 0x00000101; +} + +int board_nand_init(struct nand_chip *nand) +{ + nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA; + nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA; + nand->chip_delay = 0; + nand->select_chip = nand_davinci_select_chip; +#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT + nand->options = NAND_USE_FLASH_BBT; +#endif +#ifdef CONFIG_SYS_NAND_HW_ECC + nand->ecc.mode = NAND_ECC_HW; +#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC + nand->ecc.layout = &davinci_nand_ecclayout; +#ifdef CONFIG_SYS_NAND_LARGEPAGE + nand->ecc.size = 2048; + nand->ecc.bytes = 12; +#elif defined(CONFIG_SYS_NAND_SMALLPAGE) + nand->ecc.size = 512; + nand->ecc.bytes = 3; +#else +#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" +#endif +#else + nand->ecc.size = 512; + nand->ecc.bytes = 3; +#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ + nand->ecc.calculate = nand_davinci_calculate_ecc; + nand->ecc.correct = nand_davinci_correct_data; + nand->ecc.hwctl = nand_davinci_enable_hwecc; +#else + nand->ecc.mode = NAND_ECC_SOFT; +#endif /* CONFIG_SYS_NAND_HW_ECC */ + + /* Set address of hardware control function */ + nand->cmd_ctrl = nand_davinci_hwcontrol; + + nand->dev_ready = nand_davinci_dev_ready; + nand->waitfunc = nand_davinci_waitfunc; + + nand_flash_init(); + + return(0); +} + +#else +#error "U-Boot legacy NAND support not available for DaVinci chips" +#endif +#endif /* CONFIG_SYS_USE_NAND */ diff --git a/cpu/arm926ejs/da8xx/reset.S b/cpu/arm926ejs/da8xx/reset.S new file mode 100644 index 0000000000..a687d44035 --- /dev/null +++ b/cpu/arm926ejs/da8xx/reset.S @@ -0,0 +1,77 @@ +/* + * Processor reset using WDT for TI TMS320DM644x SoC. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * ----------------------------------------------------- + * + * 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 + */ + +.globl reset_cpu +reset_cpu: + ldr r0, WDT_TGCR + mov r1, $0x08 + str r1, [r0] + ldr r1, [r0] + orr r1, r1, $0x03 + str r1, [r0] + mov r1, $0 + ldr r0, WDT_TIM12 + str r1, [r0] + ldr r0, WDT_TIM34 + str r1, [r0] + ldr r0, WDT_PRD12 + str r1, [r0] + ldr r0, WDT_PRD34 + str r1, [r0] + ldr r0, WDT_TCR + ldr r1, [r0] + orr r1, r1, $0x40 + str r1, [r0] + ldr r0, WDT_WDTCR + ldr r1, [r0] + orr r1, r1, $0x4000 + str r1, [r0] + ldr r1, WDTCR_VAL1 + str r1, [r0] + ldr r1, WDTCR_VAL2 + str r1, [r0] + nop + nop + nop + nop +reset_cpu_loop: + b reset_cpu_loop + +WDT_TGCR: + .word 0x01c21c24 +WDT_TIM12: + .word 0x01c21c10 +WDT_TIM34: + .word 0x01c21c14 +WDT_PRD12: + .word 0x01c21c18 +WDT_PRD34: + .word 0x01c21c1c +WDT_TCR: + .word 0x01c21c20 +WDT_WDTCR: + .word 0x01c21c28 +WDTCR_VAL1: + .word 0xa5c64000 +WDTCR_VAL2: + .word 0xda7e4000 diff --git a/cpu/arm926ejs/da8xx/timer.c b/cpu/arm926ejs/da8xx/timer.c new file mode 100644 index 0000000000..773735a1c8 --- /dev/null +++ b/cpu/arm926ejs/da8xx/timer.c @@ -0,0 +1,148 @@ +/* + * (C) Copyright 2003 + * Texas Instruments <www.ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 <arm926ejs.h> + +typedef volatile struct { + u_int32_t pid12; + u_int32_t emumgt; + u_int32_t na1; + u_int32_t na2; + u_int32_t tim12; + u_int32_t tim34; + u_int32_t prd12; + u_int32_t prd34; + u_int32_t tcr; + u_int32_t tgcr; + u_int32_t wdtcr; +} davinci_timer; + +davinci_timer *timer = (davinci_timer *)CONFIG_SYS_TIMERBASE; + +#define TIMER_LOAD_VAL (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ) +#define TIM_CLK_DIV 16 + +static ulong timestamp; +static ulong lastinc; + +int timer_init(void) +{ + /* We are using timer34 in unchained 32-bit mode, full speed */ + timer->tcr = 0x0; + timer->tgcr = 0x0; + timer->tgcr = 0x06 | ((TIM_CLK_DIV - 1) << 8); + timer->tim34 = 0x0; + timer->prd34 = TIMER_LOAD_VAL; + lastinc = 0; + timestamp = 0; + timer->tcr = 2 << 22; + + return(0); +} + +void reset_timer(void) +{ + timer->tcr = 0x0; + timer->tim34 = 0; + lastinc = 0; + timestamp = 0; + timer->tcr = 2 << 22; +} + +static ulong get_timer_raw(void) +{ + ulong now = timer->tim34; + + if (now >= lastinc) { + /* normal mode */ + timestamp += now - lastinc; + } else { + /* overflow ... */ + timestamp += now + TIMER_LOAD_VAL - lastinc; + } + lastinc = now; + return timestamp; +} + +ulong get_timer(ulong base) +{ + return((get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base); +} + +void set_timer(ulong t) +{ + timestamp = t; +} + +void udelay(unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + tmo = CONFIG_SYS_HZ_CLOCK / 1000; + tmo *= usec; + tmo /= (1000 * TIM_CLK_DIV); + + endtime = get_timer_raw() + tmo; + + do { + ulong now = get_timer_raw(); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return(get_timer(0)); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 3d4f8923cf..97d8985ce8 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -28,6 +28,7 @@ LIB := $(obj)libspi_flash.a COBJS-$(CONFIG_SPI_FLASH) += spi_flash.o COBJS-$(CONFIG_SPI_FLASH_ATMEL) += atmel.o COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o +COBJS-$(CONFIG_SPI_FLASH_WINBOND) += winbond.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index d1d81af0ec..fe7d9b7d6f 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -3,7 +3,7 @@ * * Copyright (C) 2008 Atmel Corporation */ -#define DEBUG +/*#define DEBUG*/ #include <common.h> #include <malloc.h> #include <spi.h> @@ -134,6 +134,11 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, flash = spi_flash_probe_atmel(spi, idcode); break; #endif +#ifdef CONFIG_SPI_FLASH_WINBOND + case 0xef: + flash = spi_flash_probe_winbond(spi, idcode); + break; +#endif #ifdef CONFIG_SPI_FLASH_STMICRO case 0x20: flash = spi_flash_probe_stmicro(spi, idcode); diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c new file mode 100644 index 0000000000..1e2b36f6ae --- /dev/null +++ b/drivers/mtd/spi/winbond.c @@ -0,0 +1,338 @@ +/* + * Copyright 2008, Network Appliance Inc. + * Author: Jason McMullan <[EMAIL PROTECTED]> + * + */ + +#include <common.h> +#include <malloc.h> +#include <spi_flash.h> + +#include "spi_flash_internal.h" + +/* M25Pxx-specific commands */ +#define CMD_W25_WREN 0x06 /* Write Enable */ +#define CMD_W25_WRDI 0x04 /* Write Disable */ +#define CMD_W25_RDSR 0x05 /* Read Status Register */ +#define CMD_W25_WRSR 0x01 /* Write Status Register */ +#define CMD_W25_READ 0x03 /* Read Data Bytes */ +#define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ +#define CMD_W25_PP 0x02 /* Page Program */ +#define CMD_W25_SE 0x20 /* Sector (4K) Erase */ +#define CMD_W25_BE 0xd8 /* Block (64K) Erase */ +#define CMD_W25_CE 0xc7 /* Chip Erase */ +#define CMD_W25_DP 0xb9 /* Deep Power-down */ +#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */ + +#define WINBOND_ID_W25X16 0x3015 +#define WINBOND_ID_W25X32 0x3016 +#define WINBOND_ID_W25X64 0x3017 + +#define WINBOND_SR_WIP (1 << 0) /* Write-in-Progress */ + +struct winbond_spi_flash_params { + uint16_t id; + /* Log2 of page size in power-of-two mode */ + uint8_t l2_page_size; + uint16_t pages_per_sector; + uint16_t sectors_per_block; + uint8_t nr_blocks; + const char *name; +}; + +struct winbond_spi_flash { + const struct winbond_spi_flash_params *params; + struct spi_flash flash; +}; + +static inline struct winbond_spi_flash * +to_winbond_spi_flash(struct spi_flash *flash) +{ + return container_of(flash, struct winbond_spi_flash, flash); +} + +static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { + { + .id = WINBOND_ID_W25X16, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 32, + .name = "W25X16", + }, + { + .id = WINBOND_ID_W25X32, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 64, + .name = "W25X32", + }, + { + .id = WINBOND_ID_W25X64, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 128, + .name = "W25X64", + }, +}; + +static int wait_state; + +static int winbond_wait_ready(struct spi_flash *flash, unsigned long timeout) +{ + struct spi_slave *spi = flash->spi; + unsigned long timebase; + int ret; + u8 status; + u8 cmd[4] = { CMD_W25_RDSR, 0xff, 0xff, 0xff }; + + ret = spi_xfer(spi, 32, &cmd[0], NULL, SPI_XFER_BEGIN); + if (ret) { + debug("SF: Failed to send command %02x: %d\n", cmd, ret); + return ret; + } + + timebase = get_timer(0); + do { + ret = spi_xfer(spi, 8, NULL, &status, 0); + if (ret) { + debug("SF: Failed to get status for cmd %02x: %d\n", cmd, ret); + return -1; + } + + if ((status & WINBOND_SR_WIP) == 0) + break; + else if ((status & WINBOND_SR_WIP) == 1) + wait_state++; + + } while (1 || (get_timer(timebase) < timeout)); + + spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); + + if ((status & WINBOND_SR_WIP) == 0) + return 0; + + debug("SF: Timed out on command %02x: %d\n", cmd, ret); + /* Timed out */ + return -1; +} + +/* + * Assemble the address part of a command for Winbond devices in + * non-power-of-two page size mode. + */ +static void winbond_build_address(struct winbond_spi_flash *stm, u8 *cmd, u32 offset) +{ + unsigned long page_addr; + unsigned long byte_addr; + unsigned long page_size; + unsigned int page_shift; + + /* + * The "extra" space per page is the power-of-two page size + * divided by 32. + */ + page_shift = stm->params->l2_page_size; + page_size = (1 << page_shift); + page_addr = offset / page_size; + byte_addr = offset % page_size; + + cmd[0] = page_addr >> (16 - page_shift); + cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8); + cmd[2] = byte_addr; +} + +static int winbond_read_fast(struct spi_flash *flash, + u32 offset, size_t len, void *buf) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + u8 cmd[5]; + + cmd[0] = CMD_READ_ARRAY_FAST; + winbond_build_address(stm, cmd + 1, offset); + cmd[4] = 0x00; + + return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len); +} + +static int winbond_write(struct spi_flash *flash, + u32 offset, size_t len, const void *buf) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + unsigned long page_addr; + unsigned long byte_addr; + unsigned long page_size; + unsigned int page_shift; + size_t chunk_len; + size_t actual; + int ret; + u8 cmd[4]; + + page_shift = stm->params->l2_page_size; + page_size = (1 << page_shift); + page_addr = offset / page_size; + byte_addr = offset % page_size; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + for (actual = 0; actual < len; actual += chunk_len) { + chunk_len = min(len - actual, page_size - byte_addr); + + cmd[0] = CMD_W25_PP; + cmd[1] = page_addr >> (16 - page_shift); + cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8); + cmd[3] = byte_addr; + debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n", + buf + actual, + cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); + + ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); + if (ret < 0) { + debug("SF: Enabling Write failed\n"); + goto out; + } + + ret = spi_flash_cmd_write(flash->spi, cmd, 4, + buf + actual, chunk_len); + if (ret < 0) { + debug("SF: Winbond Page Program failed\n"); + goto out; + } + + ret = winbond_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret < 0) { + debug("SF: Winbond page programming timed out\n"); + goto out; + } + + page_addr++; + byte_addr = 0; + } + + printf("Number of times wait: %d\n", wait_state); + wait_state = 0; + + debug("SF: Winbond: Successfully programmed %u bytes @ 0x%x\n", + len, offset); + ret = 0; + +out: + spi_release_bus(flash->spi); + return ret; +} + +int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + unsigned long sector_size; + unsigned int page_shift; + size_t actual; + int ret; + u8 cmd[4]; + + /* + * This function currently uses sector erase only. + * probably speed things up by using bulk erase + * when possible. + */ + + page_shift = stm->params->l2_page_size; + sector_size = (1 << page_shift) * stm->params->pages_per_sector; + + if (offset % sector_size || len % sector_size) { + debug("SF: Erase offset/length not multiple of sector size\n"); + return -1; + } + + len /= sector_size; + cmd[0] = CMD_W25_SE; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + for (actual = 0; actual < len; actual++) { + winbond_build_address(stm, &cmd[1], offset + actual * sector_size); + printf("Erase: %02x %02x %02x %02x\n", + cmd[0], cmd[1], cmd[2], cmd[3]); + + ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); + if (ret < 0) { + debug("SF: Enabling Write failed\n"); + goto out; + } + + ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); + if (ret < 0) { + debug("SF: Winbond sector erase failed\n"); + goto out; + } + + ret = winbond_wait_ready(flash, 2 * CONFIG_SYS_HZ); /* Up to 2 seconds */ + if (ret < 0) { + debug("SF: Winbond sector erase timed out\n"); + goto out; + } + } + + debug("SF: Winbond: Successfully erased %u bytes @ 0x%x\n", + len * sector_size, offset); + ret = 0; + +out: + spi_release_bus(flash->spi); + return ret; +} + +struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) +{ + const struct winbond_spi_flash_params *params; + unsigned long page_size; + struct winbond_spi_flash *stm; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) { + params = &winbond_spi_flash_table[i]; + if (params->id == ((idcode[1] << 8) | idcode[2])) + break; + } + + if (i == ARRAY_SIZE(winbond_spi_flash_table)) { + debug("SF: Unsupported Winbond ID %02x%02x\n", + idcode[1], idcode[2]); + return NULL; + } + + stm = malloc(sizeof(struct winbond_spi_flash)); + if (!stm) { + debug("SF: Failed to allocate memory\n"); + return NULL; + } + + stm->params = params; + stm->flash.spi = spi; + stm->flash.name = params->name; + + /* Assuming power-of-two page size initially. */ + page_size = 1 << params->l2_page_size; + + stm->flash.write = winbond_write; + stm->flash.erase = winbond_erase; + stm->flash.read = winbond_read_fast; + stm->flash.size = page_size * params->pages_per_sector + * params->sectors_per_block + * params->nr_blocks; + + debug("SF: Detected %s with page size %u, total %u bytes\n", + params->name, page_size, stm->flash.size); + + return &stm->flash; +} diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 15e0f7a66d..bf6e66719a 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -29,6 +29,7 @@ COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o +COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c new file mode 100644 index 0000000000..ed895212bd --- /dev/null +++ b/drivers/spi/davinci_spi.c @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc <www.ti.com> + * + * Driver for SPI controller on DaVinci. Based on atmel_spi.c + * by Atmel Corporation + * + * Copyright (C) 2007 Atmel Corporation + * + * 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 <spi.h> +#include <malloc.h> + +#include <asm/io.h> + +#include <asm/arch/hardware.h> + +#include "davinci_spi.h" + +static unsigned int data1_reg_val; + + +void spi_init() +{ + /* do nothing */ + +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct davinci_spi_slave *ds; + void *regs; + unsigned int fmt0; + + ds = malloc(sizeof(struct davinci_spi_slave)); + if (!ds) + return NULL; + + ds->slave.bus = bus; + ds->slave.cs = cs; + ds->regs = CFG_SPI_BASE; + ds->freq = max_hz; + + return &ds->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct davinci_spi_slave *ds = to_davinci_spi(slave); + + free(ds); +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct davinci_spi_slave *ds = to_davinci_spi(slave); + unsigned int scalar; + + /* Enable the SPI hardware */ + spi_writel(ds, GCR0, 0); + udelay(1000); + spi_writel(ds, GCR0, 1); + + /* Set master mode, powered up and not activated */ + spi_writel(ds, GCR1, 0x3); + + /* CS, CLK, SIMO and SOMI are functional pins */ + spi_writel(ds, PC0, (1 << 0) | (1 << 9) | (1 << 10) | (1 << 11)); + + /* setup format */ + scalar = ((CFG_SPI_CLK / ds->freq) - 1 ) & 0xFF; + + spi_writel(ds, FMT0, 8 | /* character length */ + (scalar << 8) | + (1 << 16) | /* clock signal delayed by half clk cycle */ + (0 << 17) | /* clock low in idle state - Mode 0 */ + (0 << 20)); /* MSB shifted out first */ + + /* hold cs active at end of transfer until explicitly de-asserted */ + data1_reg_val = (1 << 28) | (slave->cs << 16); + spi_writel(ds, DAT1, data1_reg_val); + + /* including a minor delay. No science here. Should be good even with + * no delay + */ + spi_writel(ds, DELAY, (50 << 24) | (50 << 16)); + + /* default chip select register */ + spi_writel(ds, DEF, 1); + + /* no interrupts */ + spi_writel(ds, INT0, 0); + spi_writel(ds, LVL, 0); + + /* enable SPI */ + spi_writel(ds, GCR1, spi_readl(ds, GCR1) | (1 << 24)); + + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + struct davinci_spi_slave *ds = to_davinci_spi(slave); + + /* Disable the SPI hardware */ + spi_writel(ds, GCR0, 0); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct davinci_spi_slave *ds = to_davinci_spi(slave); + unsigned int len_tx; + unsigned int len_rx; + unsigned int len; + int ret, i; + u32 status; + const u8 *txp = dout; + u8 *rxp = din; + u8 value, dummy = 0; + + ret = 0; + + if (bitlen == 0) + /* Finish any previously submitted transfers */ + goto out; + + /* + * It's not clear how non-8-bit-aligned transfers are supposed to be + * represented as a stream of bytes...this is a limitation of + * the current SPI interface - here we terminate on receiving such a + * transfer request. + */ + if (bitlen % 8) { + /* Errors always terminate an ongoing transfer */ + flags |= SPI_XFER_END; + goto out; + } + + len = bitlen / 8; + + /* do an empty read to clear the current contents */ + spi_readl(ds, BUF); + + /* keep writing and reading 1 byte until done */ + for (i = 0; i < len; i++) { + + /* wait till TXFULL is asserted */ + while(spi_readl(ds, BUF) & (1 << 29)); + + /* write the data */ + data1_reg_val &= ~0xFFFF; + if(txp) { + data1_reg_val |= *txp & 0xFF; + txp++; + } + + /* write to DAT1 is required to keep the serial transfer going */ + /* we just terminate when we reach the end */ + if((i == (len -1)) && (flags & SPI_XFER_END)) { + spi_writel(ds, DAT1, data1_reg_val & ~(1 << 28)); /* clear CS hold */ + } else { + spi_writel(ds, DAT1, data1_reg_val); + } + + + /* read the data - wait for data availability */ + while(spi_readl(ds, BUF) & (1 << 31)); + + if(rxp) { + *rxp = spi_readl(ds, BUF) & 0xFF; + rxp++; + } else { + spi_readl(ds, BUF); /* simply drop the read character */ + } + + } + + return 0; + +out: + if (flags & SPI_XFER_END) { + spi_writel(ds, DAT1, data1_reg_val & ~(1 << 28)); + } + + return 0; +} + + +#ifdef CONFIG_CMD_EEPROM + +/* ------------------------------------------------------------------------ * + * SPI ROM Definitions * + * ------------------------------------------------------------------------ */ +#define SPIROM_SIZE 0x00008000 +#define SPIROM_BASE 0x00000000 +#define SPIROM_PAGESIZE 32 +#define SPIROM_PAGEMASK 0xffffffc0 + +/* ------------------------------------------------------------------------ * + * SPI ROM Commands * + * ------------------------------------------------------------------------ */ +#define SPIROM_CMD_WRSR 0x01 +#define SPIROM_CMD_WRITE 0x02 +#define SPIROM_CMD_READ 0x03 +#define SPIROM_CMD_WRDI 0x04 +#define SPIROM_CMD_RDSR 0x05 +#define SPIROM_CMD_WREN 0x06 + +static struct spi_slave *slave; + +void spi_init_f(void) +{ + slave = spi_setup_slave(0, 0, 1*1024*1024, 0); + spi_claim_bus(slave); +} + +static char spirombuf[3]; + +/* ------------------------------------------------------------------------ * + * spirom_status( ) * + * ------------------------------------------------------------------------ */ +static unsigned char spi_get_status( ) +{ + /* Issue read status command */ + spirombuf[0] = SPIROM_CMD_RDSR; + spirombuf[1] = 0; + + spi_xfer(slave, (2)*8, spirombuf, spirombuf, SPI_XFER_BEGIN | SPI_XFER_END); + + return spirombuf[1]; +} + +ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len) +{ + + spirombuf[0] = SPIROM_CMD_WREN; + spi_xfer(slave, 1*8, spirombuf, NULL, SPI_XFER_BEGIN | SPI_XFER_END); + + /* Create command block for program operation */ + spirombuf[0] = SPIROM_CMD_WRITE; + spirombuf[1] = addr[0]; + spirombuf[2] = addr[1]; + + spi_xfer(slave, 3 * 8, spirombuf, NULL, SPI_XFER_BEGIN); + spi_xfer(slave, len * 8, buffer, NULL, SPI_XFER_END); + + /* Wait while busy */ + while( (spi_get_status( ) & 0x01 ) ); + + return len; +} + +ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len) +{ + spirombuf[0] = 0x3; + spirombuf[1] = addr[0]; + spirombuf[2] = addr[1]; + + spi_xfer(slave, 3*8, spirombuf, NULL, SPI_XFER_BEGIN); + spi_xfer(slave, len*8, NULL, buffer, SPI_XFER_END); + + return len; +} + +#endif diff --git a/drivers/spi/davinci_spi.h b/drivers/spi/davinci_spi.h new file mode 100644 index 0000000000..0f2b0877ba --- /dev/null +++ b/drivers/spi/davinci_spi.h @@ -0,0 +1,46 @@ +/* + * Register definitions for the DaVinci SPI Controller + */ + +/* Register offsets */ +#define DAVINCI_SPI_GCR0 0x0000 +#define DAVINCI_SPI_GCR1 0x0004 +#define DAVINCI_SPI_INT0 0x0008 +#define DAVINCI_SPI_LVL 0x000c +#define DAVINCI_SPI_FLG 0x0010 +#define DAVINCI_SPI_PC0 0x0014 +#define DAVINCI_SPI_PC1 0x0018 +#define DAVINCI_SPI_PC2 0x001c +#define DAVINCI_SPI_PC3 0x0020 +#define DAVINCI_SPI_PC4 0x0024 +#define DAVINCI_SPI_PC5 0x0028 +#define DAVINCI_SPI_DAT0 0x0038 +#define DAVINCI_SPI_DAT1 0x003c +#define DAVINCI_SPI_BUF 0x0040 +#define DAVINCI_SPI_EMU 0x0044 +#define DAVINCI_SPI_DELAY 0x0048 +#define DAVINCI_SPI_DEF 0x004c +#define DAVINCI_SPI_FMT0 0x0050 +#define DAVINCI_SPI_FMT1 0x0054 +#define DAVINCI_SPI_FMT2 0x0058 +#define DAVINCI_SPI_FMT3 0x005c +#define DAVINCI_SPI_INTVEC0 0x0060 +#define DAVINCI_SPI_INTVEC1 0x0064 + +struct davinci_spi_slave { + struct spi_slave slave; + void *regs; + u32 mr; + unsigned int freq; +}; + +static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) +{ + return container_of(slave, struct davinci_spi_slave, slave); +} + +#define spi_readl(as, reg) \ + readl(CFG_SPI_BASE + DAVINCI_SPI_##reg) +#define spi_writel(as, reg, value) \ + writel(value, CFG_SPI_BASE + DAVINCI_SPI_##reg) + diff --git a/drivers/spi/spirom.c b/drivers/spi/spirom.c new file mode 100644 index 0000000000..f367335c0a --- /dev/null +++ b/drivers/spi/spirom.c @@ -0,0 +1,212 @@ +/* + * Copyright 2007 b7 Spectrum Digital Incorporated. + * All rights reserved. Property of Spectrum Digital Incorporated. + */ + +/* + * SPI ROM interface + * + */ + +#include "spirom.h" + +static Uint8 spirombuf[SPIROM_PAGESIZE + 5]; +static Uint8 statusbuf[8]; +static Uint32 spidat1; + +/* ------------------------------------------------------------------------ * + * * + * _wait( delay ) * + * Wait in a software loop for 'x' delay * + * * + * ------------------------------------------------------------------------ */ +void DAVINCIHD_wait( Uint32 delay ) +{ + volatile Uint32 i; + for ( i = 0 ; i < delay ; i++ ){ }; +} + + +/* ------------------------------------------------------------------------ * + * spirom_init( ) * + * ------------------------------------------------------------------------ */ +void spirom_init( ) +{ + /* Reset SPI */ + SPI_SPIGCR0 = 0; + _wait( 1000 ); + + /* Release SPI */ + SPI_SPIGCR0 = 1; + + /* SPI 4-Pin Mode setup */ + SPI_SPIGCR1 = 0 + | ( 0 << 24 ) + | ( 0 << 16 ) + | ( 1 << 1 ) + | ( 1 << 0 ); + + SPI_SPIPC0 = 0 + | ( 1 << 11 ) // DI + | ( 1 << 10 ) // DO + | ( 1 << 9 ) // CLK + | ( 1 << 1 ) // EN1 + | ( 1 << 0 ); // EN0 + + SPI_SPIFMT0 = 0 + | ( 0 << 20 ) // SHIFTDIR + | ( 0 << 17 ) // Polarity + | ( 1 << 16 ) // Phase + | ( 50 << 8 ) // Prescale + | ( 8 << 0 ); // Char Len + + spidat1 = 0 + | ( 1 << 28 ) // CSHOLD + | ( 0 << 24 ) // Format [0] + | ( 2 << 16 ) // CSNR [only CS0 enbled] + | ( 0 << 0 ); // + + SPI_SPIDAT1 = spidat1; + + SPI_SPIDELAY = 0 + | ( 8 << 24 ) // C2TDELAY + | ( 8 << 16 ); // T2CDELAY + + SPI_SPIDEF = 0 + | ( 1 << 1 ) // EN1 inactive high + | ( 1 << 0 ); // EN0 inactive high + + SPI_SPIINT = 0 + | ( 0 << 16 ) // + | ( 0 << 8 ) // + | ( 0 << 6 ) // + | ( 1 << 4 ); // + + SPI_SPILVL = 0 + | ( 0 << 8 ) // EN0 + | ( 0 << 6 ) // EN0 + | ( 0 << 4 ); // EN0 + + + /* Enable SPI */ + SPI_SPIGCR1 |= ( 1 << 24 ); +} + +/* ------------------------------------------------------------------------ * + * spirom_cycle( buf, len ) * + * * + * Execute a SPI spirom data transfer cycle. Each byte in buf is shifted * + * out and replaced with data coming back from the spirom. * + * ------------------------------------------------------------------------ */ +void spirom_cycle( Uint8 *buf, Uint16 len ) +{ + Uint16 i; + + /* Clear any old data */ + SPI_SPIBUF; + + /* SPIROM access cycle */ + for ( i = 0 ; i <= len ; i++ ) + { + /* Wait for transmit ready */ + while ( SPI_SPIBUF & 0x10000000 ); + + if ( i == len ) + SPI_SPIDAT1 = ( spidat1 & 0x0ffcffff ) | buf[i]; + else + SPI_SPIDAT1 = spidat1 | buf[i]; + + /* Wait for receive data ready */ + while ( SPI_SPIBUF & 0x80000000 ); + + /* Read 1 byte */ + buf[i] = SPI_SPIBUF; + } +} + +/* ------------------------------------------------------------------------ * + * spirom_status( ) * + * ------------------------------------------------------------------------ */ +Uint8 spirom_status( ) +{ + /* Issue read status command */ + statusbuf[0] = SPIROM_CMD_RDSR; + statusbuf[1] = 0; + + spirom_cycle( statusbuf, 2 ); + + return statusbuf[1]; +} + +/* ------------------------------------------------------------------------ * + * spirom_read( src, dst, length ) * + * ------------------------------------------------------------------------ */ +void spirom_read( Uint16 src, Uint32 dst, Uint32 length ) +{ + Int32 i; + Uint8 *psrc, *pdst; + + // Setup command + spirombuf[0] = SPIROM_CMD_READ; + spirombuf[1] = ( src >> 8 ); + spirombuf[2] = ( src >> 0 ); + + // Execute spirom read cycle + spirom_cycle( spirombuf, length + 3 ); + + // Copy returned data + pdst = ( Uint8 * )dst; + psrc = spirombuf + 3; + for ( i = 0 ; i < length ; i++ ) + *pdst++ = *psrc++; +} + +/* ------------------------------------------------------------------------ * + * spirom_write( src, dst, length ) * + * ------------------------------------------------------------------------ */ +void spirom_write( Uint32 src, Uint16 dst, Uint32 length ) +{ + Int32 i; + Int32 bytes_left; + Int32 bytes_to_program; + Uint8 *psrc; + + /* Establish source */ + psrc = ( Uint8 * )src; + bytes_left = length; + + while ( bytes_left > 0 ) + { + bytes_to_program = bytes_left; + + /* Most to program is SPIROM_CMD_BLOCKSIZE */ + if ( bytes_to_program > SPIROM_PAGESIZE ) + bytes_to_program = SPIROM_PAGESIZE; + + /* Make sure you don't run off the end of a block */ + if ( ( dst & SPIROM_PAGEMASK ) != ( ( dst + bytes_to_program ) & SPIROM_PAGEMASK ) ) + bytes_to_program -= ( dst + bytes_to_program ) - ( ( dst + bytes_to_program ) & SPIROM_PAGEMASK ); + + /* Issue WPEN */ + spirombuf[0] = SPIROM_CMD_WREN; + spirom_cycle( spirombuf, 0 ); + + /* Create command block for program operation */ + spirombuf[0] = SPIROM_CMD_WRITE; + spirombuf[1] = ( Uint8 )( dst >> 8 ); + spirombuf[2] = ( Uint8 )( dst ); + + for ( i = 0 ; i < bytes_to_program ; i++ ) + spirombuf[3+i] = *psrc++; + + /* Execute write command */ + spirom_cycle( spirombuf, bytes_to_program + 2 ); + + /* Wait while busy */ + while( ( spirom_status( ) & 0x01 ) ); + + /* Get ready for next iteration */ + bytes_left -= bytes_to_program; + dst += bytes_to_program; + } +} diff --git a/drivers/spi/spirom.h b/drivers/spi/spirom.h new file mode 100644 index 0000000000..b945f59ce0 --- /dev/null +++ b/drivers/spi/spirom.h @@ -0,0 +1,77 @@ +/* + * Copyright 2007 by Spectrum Digital Incorporated. + * All rights reserved. Property of Spectrum Digital Incorporated. + */ + +/* + * SPI ROM header file + * + */ + +#ifndef SPIROM_ +#define SPIROM_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "davincihd.h" + +/* ------------------------------------------------------------------------ * + * SPI ROM Definitions * + * ------------------------------------------------------------------------ */ +#define SPIROM_SIZE 0x00008000 +#define SPIROM_BASE 0x00000000 +#define SPIROM_PAGESIZE 32 +#define SPIROM_PAGEMASK 0xffffffc0 + +/* ------------------------------------------------------------------------ * + * SPI ROM Commands * + * ------------------------------------------------------------------------ */ +#define SPIROM_CMD_WRSR 0x01 +#define SPIROM_CMD_WRITE 0x02 +#define SPIROM_CMD_READ 0x03 +#define SPIROM_CMD_WRDI 0x04 +#define SPIROM_CMD_RDSR 0x05 +#define SPIROM_CMD_WREN 0x06 + +/* ------------------------------------------------------------------------ * + * SPI Controller * + * ------------------------------------------------------------------------ */ +#define SPI_BASE 0x01c66800 +#define SPI_SPIGCR0 *( volatile Uint32* )( SPI_BASE + 0x0 ) +#define SPI_SPIGCR1 *( volatile Uint32* )( SPI_BASE + 0x4 ) +#define SPI_SPIINT *( volatile Uint32* )( SPI_BASE + 0x8 ) +#define SPI_SPILVL *( volatile Uint32* )( SPI_BASE + 0xc ) +#define SPI_SPIFLG *( volatile Uint32* )( SPI_BASE + 0x10 ) +#define SPI_SPIPC0 *( volatile Uint32* )( SPI_BASE + 0x14 ) +#define SPI_SPIPC2 *( volatile Uint32* )( SPI_BASE + 0x1c ) +#define SPI_SPIDAT1_TOP *( volatile Uint16* )( SPI_BASE + 0x3c ) +#define SPI_SPIDAT1 *( volatile Uint32* )( SPI_BASE + 0x3c ) +#define SPI_SPIDAT1_PTR16 *( volatile Uint16* )( SPI_BASE + 0x3e ) +#define SPI_SPIDAT1_PTR8 *( volatile Uint8* ) ( SPI_BASE + 0x3f ) +#define SPI_SPIBUF *( volatile Uint32* )( SPI_BASE + 0x40 ) +#define SPI_SPIBUF_PTR16 *( volatile Uint16* )( SPI_BASE + 0x42 ) +#define SPI_SPIBUF_PTR8 *( volatile Uint8* ) ( SPI_BASE + 0x43 ) +#define SPI_SPIEMU *( volatile Uint32* )( SPI_BASE + 0x44 ) +#define SPI_SPIDELAY *( volatile Uint32* )( SPI_BASE + 0x48 ) +#define SPI_SPIDEF *( volatile Uint32* )( SPI_BASE + 0x4c ) +#define SPI_SPIFMT0 *( volatile Uint32* )( SPI_BASE + 0x50 ) +#define SPI_SPIFMT1 *( volatile Uint32* )( SPI_BASE + 0x54 ) +#define SPI_SPIFMT2 *( volatile Uint32* )( SPI_BASE + 0x58 ) +#define SPI_SPIFMT3 *( volatile Uint32* )( SPI_BASE + 0x5c ) +#define SPI_INTVEC0 *( volatile Uint32* )( SPI_BASE + 0x60 ) +#define SPI_INTVEC1 *( volatile Uint32* )( SPI_BASE + 0x64 ) + +/* ------------------------------------------------------------------------ * + * Prototype * + * ------------------------------------------------------------------------ */ +void spirom_init( ); +void spirom_read( Uint16 src, Uint32 dst, Uint32 length ); +void spirom_write( Uint32 src, Uint16 dst, Uint32 length ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/asm-arm/arch-da8xx/emac_defs.h b/include/asm-arm/arch-da8xx/emac_defs.h new file mode 100644 index 0000000000..6120a595e3 --- /dev/null +++ b/include/asm-arm/arch-da8xx/emac_defs.h @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Based on: + * + * ---------------------------------------------------------------------------- + * + * dm644x_emac.h + * + * TI DaVinci (DM644X) EMAC peripheral driver header for DV-EVM + * + * Copyright (C) 2005 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + + * Modifications: + * ver. 1.0: Sep 2005, TI PSP Team - Created EMAC version for uBoot. + * + */ + +#ifndef _DM644X_EMAC_H_ +#define _DM644X_EMAC_H_ + +#include <asm/arch/hardware.h> + +#define EMAC_BASE_ADDR DAVINCI_EMAC_CNTRL_REGS_BASE +#define EMAC_WRAPPER_BASE_ADDR DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE +#define EMAC_WRAPPER_RAM_ADDR DAVINCI_EMAC_WRAPPER_RAM_BASE +#define EMAC_MDIO_BASE_ADDR DAVINCI_MDIO_CNTRL_REGS_BASE + +/* MDIO module input frequency */ +#define EMAC_MDIO_BUS_FREQ clk_get(DAVINCI_MDIO_CLKID) + +/* MDIO clock output frequency */ +#define EMAC_MDIO_CLOCK_FREQ 2000000 /* 2.0 MHz */ + +/* Ethernet Min/Max packet size */ +#define EMAC_MIN_ETHERNET_PKT_SIZE 60 +#define EMAC_MAX_ETHERNET_PKT_SIZE 1518 +#define EMAC_PKT_ALIGN 18 /* 1518 + 18 = 1536 (packet aligned on 32 byte boundry) */ + +/* Number of RX packet buffers + * NOTE: Only 1 buffer supported as of now + */ +#define EMAC_MAX_RX_BUFFERS 10 + + +/*********************************************** + ******** Internally used macros *************** + ***********************************************/ + +#define EMAC_CH_TX 1 +#define EMAC_CH_RX 0 + +/* Each descriptor occupies 4 words, lets start RX desc's at 0 and + * reserve space for 64 descriptors max + */ +#define EMAC_RX_DESC_BASE 0x0 +#define EMAC_TX_DESC_BASE 0x1000 + +/* EMAC Teardown value */ +#define EMAC_TEARDOWN_VALUE 0xfffffffc + +/* MII Status Register */ +#define MII_STATUS_REG 1 + +/* Number of statistics registers */ +#define EMAC_NUM_STATS 36 + + +/* EMAC Descriptor */ +typedef volatile struct _emac_desc +{ + u_int32_t next; /* Pointer to next descriptor in chain */ + u_int8_t *buffer; /* Pointer to data buffer */ + u_int32_t buff_off_len; /* Buffer Offset(MSW) and Length(LSW) */ + u_int32_t pkt_flag_len; /* Packet Flags(MSW) and Length(LSW) */ +} emac_desc; + +/* CPPI bit positions */ +#define EMAC_CPPI_SOP_BIT (0x80000000) +#define EMAC_CPPI_EOP_BIT (0x40000000) +#define EMAC_CPPI_OWNERSHIP_BIT (0x20000000) +#define EMAC_CPPI_EOQ_BIT (0x10000000) +#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT (0x08000000) +#define EMAC_CPPI_PASS_CRC_BIT (0x04000000) + +#define EMAC_CPPI_RX_ERROR_FRAME (0x03fc0000) + +#define EMAC_MACCONTROL_RMIISPEED_100 (1 << 15) +#define EMAC_MACCONTROL_MIIEN_ENABLE (0x20) +#define EMAC_MACCONTROL_FULLDUPLEX_ENABLE (0x1) + +#define EMAC_RXMBPENABLE_RXCAFEN_ENABLE (0x200000) +#define EMAC_RXMBPENABLE_RXBROADEN (0x2000) + + +#define MDIO_CONTROL_IDLE (0x80000000) +#define MDIO_CONTROL_ENABLE (0x40000000) +#define MDIO_CONTROL_FAULT_ENABLE (0x40000) +#define MDIO_CONTROL_FAULT (0x80000) +#define MDIO_USERACCESS0_GO (0x80000000) +#define MDIO_USERACCESS0_WRITE_READ (0x0) +#define MDIO_USERACCESS0_WRITE_WRITE (0x40000000) +#define MDIO_USERACCESS0_ACK (0x20000000) + +/* Ethernet MAC Registers Structure */ +typedef struct { + dv_reg TXIDVER; + dv_reg TXCONTROL; + dv_reg TXTEARDOWN; + u_int8_t RSVD0[4]; + dv_reg RXIDVER; + dv_reg RXCONTROL; + dv_reg RXTEARDOWN; + u_int8_t RSVD1[100]; + dv_reg TXINTSTATRAW; + dv_reg TXINTSTATMASKED; + dv_reg TXINTMASKSET; + dv_reg TXINTMASKCLEAR; + dv_reg MACINVECTOR; + u_int8_t RSVD2[12]; + dv_reg RXINTSTATRAW; + dv_reg RXINTSTATMASKED; + dv_reg RXINTMASKSET; + dv_reg RXINTMASKCLEAR; + dv_reg MACINTSTATRAW; + dv_reg MACINTSTATMASKED; + dv_reg MACINTMASKSET; + dv_reg MACINTMASKCLEAR; + u_int8_t RSVD3[64]; + dv_reg RXMBPENABLE; + dv_reg RXUNICASTSET; + dv_reg RXUNICASTCLEAR; + dv_reg RXMAXLEN; + dv_reg RXBUFFEROFFSET; + dv_reg RXFILTERLOWTHRESH; + u_int8_t RSVD4[8]; + dv_reg RX0FLOWTHRESH; + dv_reg RX1FLOWTHRESH; + dv_reg RX2FLOWTHRESH; + dv_reg RX3FLOWTHRESH; + dv_reg RX4FLOWTHRESH; + dv_reg RX5FLOWTHRESH; + dv_reg RX6FLOWTHRESH; + dv_reg RX7FLOWTHRESH; + dv_reg RX0FREEBUFFER; + dv_reg RX1FREEBUFFER; + dv_reg RX2FREEBUFFER; + dv_reg RX3FREEBUFFER; + dv_reg RX4FREEBUFFER; + dv_reg RX5FREEBUFFER; + dv_reg RX6FREEBUFFER; + dv_reg RX7FREEBUFFER; + dv_reg MACCONTROL; + dv_reg MACSTATUS; + dv_reg EMCONTROL; + dv_reg FIFOCONTROL; + dv_reg MACCONFIG; + dv_reg SOFTRESET; + u_int8_t RSVD5[88]; + dv_reg MACSRCADDRLO; + dv_reg MACSRCADDRHI; + dv_reg MACHASH1; + dv_reg MACHASH2; + dv_reg BOFFTEST; + dv_reg TPACETEST; + dv_reg RXPAUSE; + dv_reg TXPAUSE; + u_int8_t RSVD6[16]; + dv_reg RXGOODFRAMES; + dv_reg RXBCASTFRAMES; + dv_reg RXMCASTFRAMES; + dv_reg RXPAUSEFRAMES; + dv_reg RXCRCERRORS; + dv_reg RXALIGNCODEERRORS; + dv_reg RXOVERSIZED; + dv_reg RXJABBER; + dv_reg RXUNDERSIZED; + dv_reg RXFRAGMENTS; + dv_reg RXFILTERED; + dv_reg RXQOSFILTERED; + dv_reg RXOCTETS; + dv_reg TXGOODFRAMES; + dv_reg TXBCASTFRAMES; + dv_reg TXMCASTFRAMES; + dv_reg TXPAUSEFRAMES; + dv_reg TXDEFERRED; + dv_reg TXCOLLISION; + dv_reg TXSINGLECOLL; + dv_reg TXMULTICOLL; + dv_reg TXEXCESSIVECOLL; + dv_reg TXLATECOLL; + dv_reg TXUNDERRUN; + dv_reg TXCARRIERSENSE; + dv_reg TXOCTETS; + dv_reg FRAME64; + dv_reg FRAME65T127; + dv_reg FRAME128T255; + dv_reg FRAME256T511; + dv_reg FRAME512T1023; + dv_reg FRAME1024TUP; + dv_reg NETOCTETS; + dv_reg RXSOFOVERRUNS; + dv_reg RXMOFOVERRUNS; + dv_reg RXDMAOVERRUNS; + u_int8_t RSVD7[624]; + dv_reg MACADDRLO; + dv_reg MACADDRHI; + dv_reg MACINDEX; + u_int8_t RSVD8[244]; + dv_reg TX0HDP; + dv_reg TX1HDP; + dv_reg TX2HDP; + dv_reg TX3HDP; + dv_reg TX4HDP; + dv_reg TX5HDP; + dv_reg TX6HDP; + dv_reg TX7HDP; + dv_reg RX0HDP; + dv_reg RX1HDP; + dv_reg RX2HDP; + dv_reg RX3HDP; + dv_reg RX4HDP; + dv_reg RX5HDP; + dv_reg RX6HDP; + dv_reg RX7HDP; + dv_reg TX0CP; + dv_reg TX1CP; + dv_reg TX2CP; + dv_reg TX3CP; + dv_reg TX4CP; + dv_reg TX5CP; + dv_reg TX6CP; + dv_reg TX7CP; + dv_reg RX0CP; + dv_reg RX1CP; + dv_reg RX2CP; + dv_reg RX3CP; + dv_reg RX4CP; + dv_reg RX5CP; + dv_reg RX6CP; + dv_reg RX7CP; +} emac_regs; + +/* EMAC Wrapper Registers Structure */ +typedef struct { + dv_reg REV; + dv_reg SOFTRESET; + dv_reg INTCONTROL; + dv_reg C0RXTHRESHEN; + dv_reg C0RXEN; + dv_reg C0TXEN; + dv_reg C0MISCEN; + dv_reg C1RXTHRESHEN; + dv_reg C1RXEN; + dv_reg C1TXEN; + dv_reg C1MISCEN; + dv_reg C2RXTHRESHEN; + dv_reg C2RXEN; + dv_reg C2TXEN; + dv_reg C2MISCEN; + dv_reg C0RXTHRESHSTAT; + dv_reg C0RXSTAT; + dv_reg C0TXSTAT; + dv_reg C0MISCSTAT; + dv_reg C1RXTHRESHSTAT; + dv_reg C1RXSTAT; + dv_reg C1TXSTAT; + dv_reg C1MISCSTAT; + dv_reg C2RXTHRESHSTAT; + dv_reg C2RXSTAT; + dv_reg C2TXSTAT; + dv_reg C2MISCSTAT; + dv_reg C0RXIMAX; + dv_reg C0TXIMAX; + dv_reg C1RXIMAX; + dv_reg C1TXIMAX; + dv_reg C2RXIMAX; + dv_reg C2TXIMAX; +} ewrap_regs; + + +/* EMAC MDIO Registers Structure */ +typedef struct { + dv_reg VERSION; + dv_reg CONTROL; + dv_reg ALIVE; + dv_reg LINK; + dv_reg LINKINTRAW; + dv_reg LINKINTMASKED; + u_int8_t RSVD0[8]; + dv_reg USERINTRAW; + dv_reg USERINTMASKED; + dv_reg USERINTMASKSET; + dv_reg USERINTMASKCLEAR; + u_int8_t RSVD1[80]; + dv_reg USERACCESS0; + dv_reg USERPHYSEL0; + dv_reg USERACCESS1; + dv_reg USERPHYSEL1; +} mdio_regs; + +int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data); +int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data); + +typedef struct +{ + char name[64]; + int (*init)(int phy_addr); + int (*is_phy_connected)(int phy_addr); + int (*get_link_speed)(int phy_addr); + int (*auto_negotiate)(int phy_addr); +} phy_t; + +#endif /* _DM644X_EMAC_H_ */ diff --git a/include/asm-arm/arch-da8xx/emif_defs.h b/include/asm-arm/arch-da8xx/emif_defs.h new file mode 100644 index 0000000000..646fc77469 --- /dev/null +++ b/include/asm-arm/arch-da8xx/emif_defs.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 + */ +#ifndef _EMIF_DEFS_H_ +#define _EMIF_DEFS_H_ + +#include <asm/arch/hardware.h> + +typedef struct { + dv_reg ERCSR; + dv_reg AWCCR; + dv_reg SDBCR; + dv_reg SDRCR; + dv_reg AB1CR; + dv_reg AB2CR; + dv_reg AB3CR; + dv_reg AB4CR; + dv_reg SDTIMR; + dv_reg DDRSR; + dv_reg DDRPHYCR; + dv_reg DDRPHYSR; + dv_reg TOTAR; + dv_reg TOTACTR; + dv_reg DDRPHYID_REV; + dv_reg SDSRETR; + dv_reg EIRR; + dv_reg EIMR; + dv_reg EIMSR; + dv_reg EIMCR; + dv_reg IOCTRLR; + dv_reg IOSTATR; + u_int8_t RSVD0[8]; + dv_reg NANDFCR; + dv_reg NANDFSR; + u_int8_t RSVD1[8]; + dv_reg NANDF1ECC; + dv_reg NANDF2ECC; + dv_reg NANDF3ECC; + dv_reg NANDF4ECC; +} emif_registers; + +typedef emif_registers *emifregs; +#endif diff --git a/include/asm-arm/arch-da8xx/hardware.h b/include/asm-arm/arch-da8xx/hardware.h new file mode 100644 index 0000000000..aafbd77f2f --- /dev/null +++ b/include/asm-arm/arch-da8xx/hardware.h @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc + * + * Based on hardware.h for DaVinci. Original Copyrights follow. + * + * Sergey Kubushyn <ksi@koi8.net> + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Based on: + * + * ------------------------------------------------------------------------- + * + * linux/include/asm-arm/arch-davinci/hardware.h + * + * Copyright (C) 2006 Texas Instruments. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include <config.h> + +#ifndef __ASSEMBLY__ + +#include <asm/sizes.h> + +#define REG(addr) (*(volatile unsigned int *)(addr)) +#define REG_P(addr) ((volatile unsigned int *)(addr)) + +typedef volatile unsigned int dv_reg; +typedef volatile unsigned int * dv_reg_p; + +#endif + +/* + * Base register addresses + */ +#define DAVINCI_UART0_BASE (0x01c42000) +#define DAVINCI_UART1_BASE (0x01d0c000) +#define DAVINCI_UART2_BASE (0x01d0d000) +#define DAVINCI_I2C0_BASE (0x01c22000) +#define DAVINCI_I2C1_BASE (0x01e28000) +#define DAVINCI_TIMER0_BASE (0x01c20000) +#define DAVINCI_TIMER1_BASE (0x01c21000) +#define DAVINCI_WDOG_BASE (0x01c21000) +#define DAVINCI_PLL_CNTRL0_BASE (0x01c11000) +#define DAVINCI_PSC0_BASE (0x01c10000) +#define DAVINCI_PSC1_BASE (0x01e27000) +#define DAVINCI_SPI0_BASE (0x01c41000) +#define DAVINCI_SPI1_BASE (0x01e12000) +#define DAVINCI_GPIO_BASE (0x01e26000) +#define DAVINCI_EMAC_CNTRL_REGS_BASE (0x01e23000) +#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE (0x01e22000) +#define DAVINCI_EMAC_WRAPPER_RAM_BASE (0x01e20000) +#define DAVINCI_MDIO_CNTRL_REGS_BASE (0x01e24000) +#define DAVINCI_ASYNC_EMIF_CNTRL_BASE (0x68000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE (0x40000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE (0x60000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE (0x62000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE4_BASE (0x64000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE5_BASE (0x66000000) +#define DAVINCI_DDR_EMIF_CTRL_BASE (0xb0000000) +#define DAVINCI_DDR_EMIF_DATA_BASE (0xc0000000) +#define DAVINCI_INTC_BASE (0xfffee000) +#define DAVINCI_BOOTCFG_BASE (0x01c14000) + +/* Clock IDs */ +#define DAVINCI_PLLM_CLKID (0xFF + 0) +#define DAVINCI_PLLC_CLKID (0xFF + 1) +#define DAVINCI_AUXCLK_CLKID (0xFF + 2) +#define DAVINCI_MDIO_CLKID 4 +#define DAVINCI_SPI0_CLKID 2 +#define DAVINCI_UART2_CLKID 2 +#define DAVINCI_ARM_CLKID 6 + +/* Power and Sleep Controller (PSC) Domains */ +#define DAVINCI_GPSC_ARMDOMAIN 0 +#define DAVINCI_GPSC_DSPDOMAIN 1 + +/* LPSCs in PSC0 */ +#define DAVINCI_LPSC_TPCC 0 +#define DAVINCI_LPSC_TPTC0 1 +#define DAVINCI_LPSC_TPTC1 2 +#define DAVINCI_LPSC_AEMIF 3 +#define DAVINCI_LPSC_SPI0 4 +#define DAVINCI_LPSC_MMC_SD 5 +#define DAVINCI_LPSC_AINTC 6 +#define DAVINCI_LPSC_ARM_RAM_ROM 7 +#define DAVINCI_LPSC_SECCTL_KEYMGR 8 +#define DAVINCI_LPSC_UART0 9 +#define DAVINCI_LPSC_SCR0 10 +#define DAVINCI_LPSC_SCR1 11 +#define DAVINCI_LPSC_SCR2 12 +#define DAVINCI_LPSC_DMAX 13 +#define DAVINCI_LPSC_ARM 14 +#define DAVINCI_LPSC_GEM 15 + +/* for LPSCs in PSC1, 32 + actual id is being used for differentiation */ +#define DAVINCI_LPSC_USB11 (32 + 1) +#define DAVINCI_LPSC_USB20 (32 + 2) +#define DAVINCI_LPSC_GPIO (32 + 3) +#define DAVINCI_LPSC_UHPI (32 + 4) +#define DAVINCI_LPSC_EMAC (32 + 5) +#define DAVINCI_LPSC_DDR_EMIF (32 + 6) +#define DAVINCI_LPSC_McASP0 (32 + 7) +#define DAVINCI_LPSC_McASP1 (32 + 8) +#define DAVINCI_LPSC_McASP2 (32 + 9) +#define DAVINCI_LPSC_SPI1 (32 + 10) +#define DAVINCI_LPSC_I2C1 (32 + 11) +#define DAVINCI_LPSC_UART1 (32 + 12) +#define DAVINCI_LPSC_UART2 (32 + 13) +#define DAVINCI_LPSC_LCDC (32 + 16) +#define DAVINCI_LPSC_ePWM (32 + 17) +#define DAVINCI_LPSC_eCAP (32 + 20) +#define DAVINCI_LPSC_eQEP (32 + 21) +#define DAVINCI_LPSC_SCR_P0 (32 + 22) +#define DAVINCI_LPSC_SCR_P1 (32 + 23) +#define DAVINCI_LPSC_CR_P3 (32 + 26) +#define DAVINCI_LPSC_L3_CBA_RAM (32 + 31) + +/* Some PSC defines */ + +#define PSC0_MDCTL (DAVINCI_PSC0_BASE + 0xa00) +#define PSC0_MDSTAT (DAVINCI_PSC0_BASE + 0x800) +#define PSC0_PTCMD (DAVINCI_PSC0_BASE + 0x120) +#define PSC0_PTSTAT (DAVINCI_PSC0_BASE + 0x128) + +#define PSC1_MDCTL (DAVINCI_PSC1_BASE + 0xa00) +#define PSC1_MDSTAT (DAVINCI_PSC1_BASE + 0x800) +#define PSC1_PTCMD (DAVINCI_PSC1_BASE + 0x120) +#define PSC1_PTSTAT (DAVINCI_PSC1_BASE + 0x128) + +/* Some PLL defines */ +#define PLL0_PLLCTL (DAVINCI_PLL_CNTRL0_BASE + 0x100) +#define PLL0_PLLM (DAVINCI_PLL_CNTRL0_BASE + 0x110) +#define PLL0_PREDIV (DAVINCI_PLL_CNTRL0_BASE + 0x114) +#define PLL0_POSTDIV (DAVINCI_PLL_CNTRL0_BASE + 0x128) +#define PLL0_DIV1 (DAVINCI_PLL_CNTRL0_BASE + 0x118) +#define PLL0_DIV2 (DAVINCI_PLL_CNTRL0_BASE + 0x11c) +#define PLL0_DIV3 (DAVINCI_PLL_CNTRL0_BASE + 0x120) +#define PLL0_DIV4 (DAVINCI_PLL_CNTRL0_BASE + 0x160) +#define PLL0_DIV5 (DAVINCI_PLL_CNTRL0_BASE + 0x164) +#define PLL0_DIV6 (DAVINCI_PLL_CNTRL0_BASE + 0x168) +#define PLL0_DIV7 (DAVINCI_PLL_CNTRL0_BASE + 0x16c) +#define PLL0_DIV8 (DAVINCI_PLL_CNTRL0_BASE + 0x170) +#define PLL0_DIV9 (DAVINCI_PLL_CNTRL0_BASE + 0x114) + +/* Boot config */ +#define KICK0 (DAVINCI_BOOTCFG_BASE + 0x38) +#define KICK1 (DAVINCI_BOOTCFG_BASE + 0x3c) +#define PINMUX0 (DAVINCI_BOOTCFG_BASE + 0x120) +#define PINMUX1 (DAVINCI_BOOTCFG_BASE + 0x124) +#define PINMUX2 (DAVINCI_BOOTCFG_BASE + 0x128) +#define PINMUX3 (DAVINCI_BOOTCFG_BASE + 0x12c) +#define PINMUX4 (DAVINCI_BOOTCFG_BASE + 0x130) +#define PINMUX5 (DAVINCI_BOOTCFG_BASE + 0x134) +#define PINMUX6 (DAVINCI_BOOTCFG_BASE + 0x138) +#define PINMUX7 (DAVINCI_BOOTCFG_BASE + 0x13c) +#define PINMUX8 (DAVINCI_BOOTCFG_BASE + 0x140) +#define PINMUX9 (DAVINCI_BOOTCFG_BASE + 0x144) +#define PINMUX10 (DAVINCI_BOOTCFG_BASE + 0x148) +#define PINMUX11 (DAVINCI_BOOTCFG_BASE + 0x14c) +#define PINMUX12 (DAVINCI_BOOTCFG_BASE + 0x150) +#define PINMUX13 (DAVINCI_BOOTCFG_BASE + 0x154) +#define PINMUX14 (DAVINCI_BOOTCFG_BASE + 0x158) +#define PINMUX15 (DAVINCI_BOOTCFG_BASE + 0x15C) +#define PINMUX16 (DAVINCI_BOOTCFG_BASE + 0x160) +#define PINMUX17 (DAVINCI_BOOTCFG_BASE + 0x164) +#define PINMUX18 (DAVINCI_BOOTCFG_BASE + 0x168) +#define PINMUX19 (DAVINCI_BOOTCFG_BASE + 0x16c) +#define SUSPSRC (DAVINCI_BOOTCFG_BASE + 0x170) +#define CFGCHIP0 (DAVINCI_BOOTCFG_BASE + 0x17c) + +/* Interrupt controller */ +#define INTC_GLB_EN (DAVINCI_INTC_BASE + 0x10) +#define INTC_HINT_EN (DAVINCI_INTC_BASE + 0x1500) +#define INTC_EN_CLR0 (DAVINCI_INTC_BASE + 0x380) + +#endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/include/asm-arm/arch-da8xx/i2c_defs.h b/include/asm-arm/arch-da8xx/i2c_defs.h new file mode 100644 index 0000000000..714211fca5 --- /dev/null +++ b/include/asm-arm/arch-da8xx/i2c_defs.h @@ -0,0 +1,95 @@ +/* + * (C) Copyright 2004 + * Texas Instruments, <www.ti.com> + * + * Some changes copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 + */ +#ifndef _DAVINCI_I2C_H_ +#define _DAVINCI_I2C_H_ + +#define I2C_WRITE 0 +#define I2C_READ 1 + +#define I2C_BASE 0x01c22000 + +#define I2C_OA (I2C_BASE + 0x00) +#define I2C_IE (I2C_BASE + 0x04) +#define I2C_STAT (I2C_BASE + 0x08) +#define I2C_SCLL (I2C_BASE + 0x0c) +#define I2C_SCLH (I2C_BASE + 0x10) +#define I2C_CNT (I2C_BASE + 0x14) +#define I2C_DRR (I2C_BASE + 0x18) +#define I2C_SA (I2C_BASE + 0x1c) +#define I2C_DXR (I2C_BASE + 0x20) +#define I2C_CON (I2C_BASE + 0x24) +#define I2C_IV (I2C_BASE + 0x28) +#define I2C_PSC (I2C_BASE + 0x30) + +/* I2C masks */ + +/* I2C Interrupt Enable Register (I2C_IE): */ +#define I2C_IE_SCD_IE (1 << 5) /* Stop condition detect interrupt enable */ +#define I2C_IE_XRDY_IE (1 << 4) /* Transmit data ready interrupt enable */ +#define I2C_IE_RRDY_IE (1 << 3) /* Receive data ready interrupt enable */ +#define I2C_IE_ARDY_IE (1 << 2) /* Register access ready interrupt enable */ +#define I2C_IE_NACK_IE (1 << 1) /* No acknowledgment interrupt enable */ +#define I2C_IE_AL_IE (1 << 0) /* Arbitration lost interrupt enable */ + +/* I2C Status Register (I2C_STAT): */ + +#define I2C_STAT_BB (1 << 12) /* Bus busy */ +#define I2C_STAT_ROVR (1 << 11) /* Receive overrun */ +#define I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ +#define I2C_STAT_AAS (1 << 9) /* Address as slave */ +#define I2C_STAT_SCD (1 << 5) /* Stop condition detect */ +#define I2C_STAT_XRDY (1 << 4) /* Transmit data ready */ +#define I2C_STAT_RRDY (1 << 3) /* Receive data ready */ +#define I2C_STAT_ARDY (1 << 2) /* Register access ready */ +#define I2C_STAT_NACK (1 << 1) /* No acknowledgment interrupt enable */ +#define I2C_STAT_AL (1 << 0) /* Arbitration lost interrupt enable */ + + +/* I2C Interrupt Code Register (I2C_INTCODE): */ + +#define I2C_INTCODE_MASK 7 +#define I2C_INTCODE_NONE 0 +#define I2C_INTCODE_AL 1 /* Arbitration lost */ +#define I2C_INTCODE_NAK 2 /* No acknowledgement/general call */ +#define I2C_INTCODE_ARDY 3 /* Register access ready */ +#define I2C_INTCODE_RRDY 4 /* Rcv data ready */ +#define I2C_INTCODE_XRDY 5 /* Xmit data ready */ +#define I2C_INTCODE_SCD 6 /* Stop condition detect */ + + +/* I2C Configuration Register (I2C_CON): */ + +#define I2C_CON_EN (1 << 5) /* I2C module enable */ +#define I2C_CON_STB (1 << 4) /* Start byte mode (master mode only) */ +#define I2C_CON_MST (1 << 10) /* Master/slave mode */ +#define I2C_CON_TRX (1 << 9) /* Transmitter/receiver mode (master mode only) */ +#define I2C_CON_XA (1 << 8) /* Expand address */ +#define I2C_CON_STP (1 << 11) /* Stop condition (master mode only) */ +#define I2C_CON_STT (1 << 13) /* Start condition (master mode only) */ +#define I2C_CON_FREE (1 << 14) /* Free run on emulation */ + +#define I2C_TIMEOUT 0xffff0000 /* Timeout mask for poll_i2c_irq() */ + +#endif diff --git a/include/asm-arm/arch-da8xx/nand_defs.h b/include/asm-arm/arch-da8xx/nand_defs.h new file mode 100644 index 0000000000..450e8b986c --- /dev/null +++ b/include/asm-arm/arch-da8xx/nand_defs.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Parts shamelesly stolen from Linux Kernel source tree. + * + * ------------------------------------------------------------ + * + * 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 + */ +#ifndef _NAND_DEFS_H_ +#define _NAND_DEFS_H_ + +#include <asm/arch/hardware.h> + +#define MASK_CLE 0x10 +//#define MASK_ALE 0x0a +#define MASK_ALE 0x08 + + +#define NAND_CE0CLE ((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x10)) +//#define NAND_CE0ALE ((volatile u_int8_t *)(CFG_NAND_BASE + 0x0a)) +#define NAND_CE0ALE ((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x08)) +#define NAND_CE0DATA ((volatile u_int8_t *)CONFIG_SYS_NAND_BASE) + +typedef struct { + u_int32_t NRCSR; + u_int32_t AWCCR; + u_int8_t RSVD0[8]; + u_int32_t AB1CR; + u_int32_t AB2CR; + u_int32_t AB3CR; + u_int32_t AB4CR; + u_int8_t RSVD1[32]; + u_int32_t NIRR; + u_int32_t NIMR; + u_int32_t NIMSR; + u_int32_t NIMCR; + u_int8_t RSVD2[16]; + u_int32_t NANDFCR; + u_int32_t NANDFSR; + u_int8_t RSVD3[8]; + u_int32_t NANDF1ECC; + u_int32_t NANDF2ECC; + u_int32_t NANDF3ECC; + u_int32_t NANDF4ECC; + u_int8_t RSVD4[4]; + u_int32_t IODFTECR; + u_int32_t IODFTGCR; + u_int8_t RSVD5[4]; + u_int32_t IODFTMRLR; + u_int32_t IODFTMRMR; + u_int32_t IODFTMRMSBR; + u_int8_t RSVD6[20]; + u_int32_t MODRNR; + u_int8_t RSVD7[76]; + u_int32_t CE0DATA; + u_int32_t CE0ALE; + u_int32_t CE0CLE; + u_int8_t RSVD8[4]; + u_int32_t CE1DATA; + u_int32_t CE1ALE; + u_int32_t CE1CLE; + u_int8_t RSVD9[4]; + u_int32_t CE2DATA; + u_int32_t CE2ALE; + u_int32_t CE2CLE; + u_int8_t RSVD10[4]; + u_int32_t CE3DATA; + u_int32_t CE3ALE; + u_int32_t CE3CLE; +} nand_registers; + +typedef volatile nand_registers *nandregs; + +#define NAND_READ_START 0x00 +#define NAND_READ_END 0x30 +#define NAND_STATUS 0x70 + +#ifdef CFG_NAND_HW_ECC +#define NAND_Ecc_P1e (1 << 0) +#define NAND_Ecc_P2e (1 << 1) +#define NAND_Ecc_P4e (1 << 2) +#define NAND_Ecc_P8e (1 << 3) +#define NAND_Ecc_P16e (1 << 4) +#define NAND_Ecc_P32e (1 << 5) +#define NAND_Ecc_P64e (1 << 6) +#define NAND_Ecc_P128e (1 << 7) +#define NAND_Ecc_P256e (1 << 8) +#define NAND_Ecc_P512e (1 << 9) +#define NAND_Ecc_P1024e (1 << 10) +#define NAND_Ecc_P2048e (1 << 11) + +#define NAND_Ecc_P1o (1 << 16) +#define NAND_Ecc_P2o (1 << 17) +#define NAND_Ecc_P4o (1 << 18) +#define NAND_Ecc_P8o (1 << 19) +#define NAND_Ecc_P16o (1 << 20) +#define NAND_Ecc_P32o (1 << 21) +#define NAND_Ecc_P64o (1 << 22) +#define NAND_Ecc_P128o (1 << 23) +#define NAND_Ecc_P256o (1 << 24) +#define NAND_Ecc_P512o (1 << 25) +#define NAND_Ecc_P1024o (1 << 26) +#define NAND_Ecc_P2048o (1 << 27) + +#define TF(v) (v ? 1 : 0) + +#define P2048e(a) (TF(a & NAND_Ecc_P2048e) << 0) +#define P2048o(a) (TF(a & NAND_Ecc_P2048o) << 1) +#define P1e(a) (TF(a & NAND_Ecc_P1e) << 2) +#define P1o(a) (TF(a & NAND_Ecc_P1o) << 3) +#define P2e(a) (TF(a & NAND_Ecc_P2e) << 4) +#define P2o(a) (TF(a & NAND_Ecc_P2o) << 5) +#define P4e(a) (TF(a & NAND_Ecc_P4e) << 6) +#define P4o(a) (TF(a & NAND_Ecc_P4o) << 7) + +#define P8e(a) (TF(a & NAND_Ecc_P8e) << 0) +#define P8o(a) (TF(a & NAND_Ecc_P8o) << 1) +#define P16e(a) (TF(a & NAND_Ecc_P16e) << 2) +#define P16o(a) (TF(a & NAND_Ecc_P16o) << 3) +#define P32e(a) (TF(a & NAND_Ecc_P32e) << 4) +#define P32o(a) (TF(a & NAND_Ecc_P32o) << 5) +#define P64e(a) (TF(a & NAND_Ecc_P64e) << 6) +#define P64o(a) (TF(a & NAND_Ecc_P64o) << 7) + +#define P128e(a) (TF(a & NAND_Ecc_P128e) << 0) +#define P128o(a) (TF(a & NAND_Ecc_P128o) << 1) +#define P256e(a) (TF(a & NAND_Ecc_P256e) << 2) +#define P256o(a) (TF(a & NAND_Ecc_P256o) << 3) +#define P512e(a) (TF(a & NAND_Ecc_P512e) << 4) +#define P512o(a) (TF(a & NAND_Ecc_P512o) << 5) +#define P1024e(a) (TF(a & NAND_Ecc_P1024e) << 6) +#define P1024o(a) (TF(a & NAND_Ecc_P1024o) << 7) + +#define P8e_s(a) (TF(a & NAND_Ecc_P8e) << 0) +#define P8o_s(a) (TF(a & NAND_Ecc_P8o) << 1) +#define P16e_s(a) (TF(a & NAND_Ecc_P16e) << 2) +#define P16o_s(a) (TF(a & NAND_Ecc_P16o) << 3) +#define P1e_s(a) (TF(a & NAND_Ecc_P1e) << 4) +#define P1o_s(a) (TF(a & NAND_Ecc_P1o) << 5) +#define P2e_s(a) (TF(a & NAND_Ecc_P2e) << 6) +#define P2o_s(a) (TF(a & NAND_Ecc_P2o) << 7) + +#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) +#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) +#endif + +#endif diff --git a/include/configs/da8xx_evm.h b/include/configs/da8xx_evm.h new file mode 100644 index 0000000000..e65989326d --- /dev/null +++ b/include/configs/da8xx_evm.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2008 Texas Instruments, Inc <www.ti.com> + * + * Based on davinci_dvevm.h. Original Copyrights follow: + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H +#include <asm/sizes.h> +#include <asm/arch/hardware.h> + +/*=======*/ +/* Board */ +/*=======*/ +//#define CFG_USE_SPIFLASH +#define CONFIG_SYS_USE_NAND + +/*===================*/ +/* SoC Configuration */ +/*===================*/ +#define CONFIG_ARM926EJS /* arm926ejs CPU core */ +#define CONFIG_DA8XX /* TI DA8xx SoC */ +#define CONFIG_SYS_CLK_FREQ clk_get(DAVINCI_ARM_CLKID) /* Arm Clock */ +#define CFG_OSCIN_FREQ 24000000 +#define CONFIG_SYS_TIMERBASE DAVINCI_TIMER0_BASE /* use timer 0 */ +#define CONFIG_SYS_HZ_CLOCK clk_get(DAVINCI_AUXCLK_CLKID) /* Timer Input clock freq */ +#define CONFIG_SYS_HZ 1000 +#undef CONFIG_SKIP_LOWLEVEL_INIT /* U-Boot is _always_ loaded by a bootloader */ +#define CONFIG_SKIP_RELOCATE_UBOOT /* to a proper address, init done */ + +/*=============*/ +/* Memory Info */ +/*=============*/ +#define CONFIG_SYS_MALLOC_LEN (0x10000 + 128*1024) /* malloc() len */ +#define CONFIG_SYS_GBL_DATA_SIZE 128 /* reserved for initial data */ +#define PHYS_SDRAM_1 DAVINCI_DDR_EMIF_DATA_BASE /* DDR Start */ +#define PHYS_SDRAM_1_SIZE 0x04000000 /* SDRAM size 64MB */ +#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 /* memtest start address */ +#define CONFIG_SYS_MEMTEST_END (PHYS_SDRAM_1 + 16*1024*1024) /* 16MB RAM test */ +#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ +#define CONFIG_STACKSIZE (256*1024) /* regular stack */ +#define SDRAM_4BANKS_10COLS /* TODO: Update this! */ + +/*====================*/ +/* Serial Driver info */ +/*====================*/ +#define CONFIG_SYS_NS16550 +#define CONFIG_SYS_NS16550_SERIAL +#define CONFIG_SYS_NS16550_REG_SIZE 4 /* NS16550 register size */ +#define CONFIG_SYS_NS16550_COM1 DAVINCI_UART2_BASE /* Base address of UART2 */ +#define CONFIG_SYS_NS16550_CLK clk_get(DAVINCI_UART2_CLKID) /* Input clock to NS16550 */ +#define CONFIG_CONS_INDEX 1 /* use UART0 for console */ +#define CONFIG_BAUDRATE 115200 /* Default baud rate */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/*===================*/ +/* I2C Configuration */ +/*===================*/ +#define CONFIG_HARD_I2C +#define CONFIG_DRIVER_DAVINCI_I2C +#define CONFIG_SYS_I2C_SPEED 25000 /* 100Kbps won't work, silicon bug */ +#define CONFIG_SYS_I2C_SLAVE 10 /* Bogus, master-only in U-Boot */ + +/*====================================================*/ +/* I2C EEPROM definitions for catalyst 24W256 EEPROM chip */ +/*====================================================*/ +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 +#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 6 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 20 + +/*==================================*/ +/* Network & Ethernet Configuration */ +/*==================================*/ +#define CONFIG_DRIVER_TI_EMAC +#define CONFIG_MII +#define CONFIG_BOOTP_DEFAULT +#define CONFIG_BOOTP_DNS +#define CONFIG_BOOTP_DNS2 +#define CONFIG_BOOTP_SEND_HOSTNAME +#define CONFIG_NET_RETRY_COUNT 10 + +/*=====================*/ +/* Flash & Environment */ +/*=====================*/ +#ifdef CONFIG_SYS_USE_NAND +#undef CONFIG_ENV_IS_IN_FLASH +#define CONFIG_SYS_NO_FLASH +#define CONFIG_ENV_IS_IN_NAND /* U-Boot env in NAND Flash */ +#define CONFIG_ENV_SIZE SZ_128K +#define CONFIG_NAND_1BIT_ECC +#define CONFIG_NAND_CS 3 +#define CONFIG_SYS_NAND_BASE DAVINCI_ASYNC_EMIF_DATA_CE3_BASE +#define CONFIG_CLE_MASK 0x10 +#define CONFIG_ALE_MASK 0x8 +#define CONFIG_NAND_HW_ECC +#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ +#define NAND_MAX_CHIPS 1 +#define CONFIG_ENV_OFFSET 0x0 /* Block 0--not used by bootcode */ +#define DEF_BOOTM "" +#endif + +#ifdef CONFIG_SYS_USE_NOR +#define CONFIG_ENV_IS_IN_FLASH +#undef CONFIG_SYS_NO_FLASH +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +#define CFG_MAX_FLASH_BANKS 1 /* max number of flash banks */ +#define CFG_FLASH_SECT_SZ 0x10000 /* 64KB sect size AMD Flash */ +#define CONFIG_ENV_OFFSET (CFG_FLASH_SECT_SZ*3) +#define CFG_FLASH_BASE DAVINCI_ASYNC_EMIF_DATA_CE2_BASE +#define PHYS_FLASH_SIZE 0x2000000 /* Flash size 32MB */ +#define CFG_MAX_FLASH_SECT (PHYS_FLASH_SIZE/CFG_FLASH_SECT_SZ) +#define CONFIG_ENV_SECT_SIZE CFG_FLASH_SECT_SZ /* Env sector Size */ +#endif + +#ifdef CFG_USE_SPIFLASH +#undef CONFIG_ENV_IS_IN_FLASH +#undef CONFIG_ENV_IS_IN_NAND +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_SIZE SZ_16K +#define CONFIG_ENV_OFFSET SZ_256K +#define CONFIG_ENV_SECT_SIZE SZ_4K +#define CONFIG_SYS_NO_FLASH +#define CONFIG_SPI +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_WINBOND +#define CONFIG_DAVINCI_SPI +#define CFG_SPI_BASE DAVINCI_SPI0_BASE +#define CFG_SPI_CLK clk_get(DAVINCI_SPI0_CLKID) +#define CONFIG_SF_DEFAULT_SPEED 50000000 +#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED +#endif + + +/*==============================*/ +/* U-Boot general configuration */ +/*==============================*/ +#undef CONFIG_USE_IRQ /* No IRQ/FIQ in U-Boot */ +#define CONFIG_MISC_INIT_R +#undef CONFIG_BOOTDELAY +#define CONFIG_BOOTFILE "uImage" /* Boot file name */ +#define CONFIG_SYS_PROMPT "U-Boot > " /* Monitor Command Prompt */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print buffer sz */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ +#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_MEMTEST_START + 0x700000) /* default Linux kernel load address */ +#define CONFIG_VERSION_VARIABLE +#define CONFIG_AUTO_COMPLETE /* Won't work with hush so far, may be later */ +#define CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " +#define CONFIG_CMDLINE_EDITING +#define CONFIG_SYS_LONGHELP +#define CONFIG_CRC32_VERIFY +#define CONFIG_MX_CYCLIC + +/*===================*/ +/* Linux Information */ +/*===================*/ +#define LINUX_BOOT_PARAM_ADDR (CONFIG_SYS_MEMTEST_START + 0x100) +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_BOOTARGS "mem=32M console=ttyS2,115200n8 root=/dev/mtdblock/2 rw noinitrd ip=dhcp" +#define CONFIG_BOOTCOMMAND "" +#define CONFIG_BOOTDELAY 3 + +/*=================*/ +/* U-Boot commands */ +/*=================*/ +#include <config_cmd_default.h> +#define CONFIG_CMD_ENV +#define CONFIG_CMD_ASKENV +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_MII +#define CONFIG_CMD_PING +#define CONFIG_CMD_SAVES +#define CONFIG_CMD_MEMORY +#undef CONFIG_CMD_BDI +#undef CONFIG_CMD_FPGA +#undef CONFIG_CMD_SETGETDCR +#define CONFIG_CMD_EEPROM + +#ifdef CONFIG_SYS_USE_NAND +#undef CONFIG_CMD_FLASH +#undef CONFIG_CMD_IMLS +#define CONFIG_CMD_NAND +#endif + +#ifdef CFG_USE_SPIFLASH +#undef CONFIG_CMD_IMLS +#undef CONFIG_CMD_FLASH +#define CONFIG_CMD_SF +#endif + +#if !defined(CONFIG_SYS_USE_NAND) && !defined(CONFIG_SYS_USE_NOR) && !defined(CFG_USE_SPIFLASH) +#define CFG_ENV_IS_NOWHERE +#define CONFIG_SYS_NO_FLASH +#define CONFIG_ENV_SIZE SZ_16K +#undef CONFIG_CMD_IMLS +#undef CONFIG_CMD_FLASH +#undef CONFIG_CMD_ENV +#endif + +#endif /* __CONFIG_H */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 24ad2bdaa1..59e64dcb7a 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -135,6 +135,15 @@ typedef enum { NAND_ECC_HW_SYNDROME, } nand_ecc_modes_t; +struct page_layout_item { + int length; + enum { + ITEM_TYPE_DATA, + ITEM_TYPE_OOB, + ITEM_TYPE_ECC, + } type; +}; + /* * Constants for Hardware ECC */ @@ -144,6 +153,9 @@ typedef enum { #define NAND_ECC_WRITE 1 /* Enable Hardware ECC before syndrom is read back from flash */ #define NAND_ECC_READSYN 2 +#define NAND_ECC_WRITESYN 3 +#define NAND_ECC_READOOB 4 +#define NAND_ECC_WRITEOOB 5 /* Bit mask for flags passed to do_nand_read_ecc */ #define NAND_GET_DEVICE 0x80 diff --git a/lib_arm/board.c b/lib_arm/board.c index 2358bebdbd..0a77f7fdb2 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -416,9 +416,9 @@ void start_armboot (void) /* Perform network card initialisation if necessary */ #ifdef CONFIG_DRIVER_TI_EMAC -extern void davinci_eth_set_mac_addr (const u_int8_t *addr); +extern void dm644x_eth_set_mac_addr (const u_int8_t *addr); if (getenv ("ethaddr")) { - davinci_eth_set_mac_addr(gd->bd->bi_enetaddr); + dm644x_eth_set_mac_addr(gd->bd->bi_enetaddr); } #endif @@ -469,7 +469,7 @@ extern int at91rm9200_miiphy_initialize(bd_t *bis); extern int emac4xx_miiphy_initialize(bd_t *bis); extern int mcf52x2_miiphy_initialize(bd_t *bis); extern int ns7520_miiphy_initialize(bd_t *bis); -extern int davinci_eth_miiphy_initialize(bd_t *bis); +extern int dm644x_eth_miiphy_initialize(bd_t *bis); int eth_initialize(bd_t *bis) @@ -491,7 +491,7 @@ int eth_initialize(bd_t *bis) ns7520_miiphy_initialize(bis); #endif #if defined(CONFIG_DRIVER_TI_EMAC) - davinci_eth_miiphy_initialize(bis); + dm644x_eth_miiphy_initialize(bis); #endif return 0; } diff --git a/patches/freon_port.patch b/patches/freon_port.patch new file mode 100644 index 0000000000..b70ce86498 --- /dev/null +++ b/patches/freon_port.patch @@ -0,0 +1,3910 @@ +Index: u-boot-2009.01-primus/include/configs/da850_evm.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/include/configs/da850_evm.h +@@ -0,0 +1,223 @@ ++/* ++ * Copyright (C) 2008 Texas Instruments, Inc <www.ti.com> ++ * ++ * Based on davinci_dvevm.h. Original Copyrights follow: ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * 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 ++ */ ++ ++#ifndef __CONFIG_H ++#define __CONFIG_H ++#include <asm/sizes.h> ++#include <asm/arch/hardware.h> ++ ++/*=======*/ ++/* Board */ ++/*=======*/ ++//#define CFG_USE_SPIFLASH ++#define CONFIG_SYS_USE_NAND ++ ++/*===================*/ ++/* SoC Configuration */ ++/*===================*/ ++#define CONFIG_ARM926EJS /* arm926ejs CPU core */ ++#define CONFIG_DA850 /* TI DA850 SoC */ ++#define CONFIG_SYS_CLK_FREQ clk_get(DAVINCI_ARM_CLKID) /* Arm Clock */ ++#define CFG_OSCIN_FREQ 24000000 ++#define CONFIG_SYS_TIMERBASE DAVINCI_TIMER0_BASE /* use timer 0 */ ++#define CONFIG_SYS_HZ_CLOCK clk_get(DAVINCI_AUXCLK_CLKID) /* Timer Input clock freq */ ++#define CONFIG_SYS_HZ 1000 ++#undef CONFIG_SKIP_LOWLEVEL_INIT /* U-Boot is _always_ loaded by a bootloader */ ++#define CONFIG_SKIP_RELOCATE_UBOOT /* to a proper address, init done */ ++ ++/*=============*/ ++/* Memory Info */ ++/*=============*/ ++#define CONFIG_SYS_MALLOC_LEN (0x10000 + 128*1024) /* malloc() len */ ++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* reserved for initial data */ ++#define PHYS_SDRAM_1 DAVINCI_DDR_EMIF_DATA_BASE /* DDR Start */ ++#define PHYS_SDRAM_1_SIZE 0x04000000 /* SDRAM size 64MB */ ++#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 /* memtest start address */ ++#define CONFIG_SYS_MEMTEST_END (PHYS_SDRAM_1 + 16*1024*1024) /* 16MB RAM test */ ++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ ++#define CONFIG_STACKSIZE (256*1024) /* regular stack */ ++#define SDRAM_4BANKS_10COLS /* TODO: Update this! */ ++ ++/*====================*/ ++/* Serial Driver info */ ++/*====================*/ ++#define CONFIG_SYS_NS16550 ++#define CONFIG_SYS_NS16550_SERIAL ++#define CONFIG_SYS_NS16550_REG_SIZE 4 /* NS16550 register size */ ++#define CONFIG_SYS_NS16550_COM1 DAVINCI_UART0_BASE /* Base address of UART2 */ ++#define CONFIG_SYS_NS16550_CLK clk_get(DAVINCI_UART0_CLKID) /* Input clock to NS16550 */ ++#define CONFIG_CONS_INDEX 1 /* use UART0 for console */ ++#define CONFIG_BAUDRATE 115200 /* Default baud rate */ ++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } ++ ++/*===================*/ ++/* I2C Configuration */ ++/*===================*/ ++#define CONFIG_HARD_I2C ++#define CONFIG_DRIVER_DAVINCI_I2C ++#define CONFIG_SYS_I2C_SPEED 25000 /* 100Kbps won't work, silicon bug */ ++#define CONFIG_SYS_I2C_SLAVE 10 /* Bogus, master-only in U-Boot */ ++ ++/*====================================================*/ ++/* I2C EEPROM definitions for catalyst 24W256 EEPROM chip */ ++/*====================================================*/ ++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 ++#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 ++#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 6 ++#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 20 ++ ++/*==================================*/ ++/* Network & Ethernet Configuration */ ++/*==================================*/ ++#define CONFIG_DRIVER_TI_EMAC ++#define CONFIG_MII ++#define CONFIG_BOOTP_DEFAULT ++#define CONFIG_BOOTP_DNS ++#define CONFIG_BOOTP_DNS2 ++#define CONFIG_BOOTP_SEND_HOSTNAME ++#define CONFIG_NET_RETRY_COUNT 10 ++ ++/*=====================*/ ++/* Flash & Environment */ ++/*=====================*/ ++#ifdef CONFIG_SYS_USE_NAND ++#undef CONFIG_ENV_IS_IN_FLASH ++#define CONFIG_SYS_NO_FLASH ++#define CONFIG_ENV_IS_IN_NAND /* U-Boot env in NAND Flash */ ++#define CONFIG_ENV_SIZE SZ_128K ++#define CONFIG_NAND_1BIT_ECC ++#define CONFIG_NAND_CS 3 ++#define CONFIG_SYS_NAND_BASE DAVINCI_ASYNC_EMIF_DATA_CE3_BASE ++#define CONFIG_CLE_MASK 0x10 ++#define CONFIG_ALE_MASK 0x8 ++#define CONFIG_NAND_HW_ECC ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ ++#define NAND_MAX_CHIPS 1 ++#define CONFIG_ENV_OFFSET 0x0 /* Block 0--not used by bootcode */ ++#define DEF_BOOTM "" ++#endif ++ ++#ifdef CONFIG_SYS_USE_NOR ++#define CONFIG_ENV_IS_IN_FLASH ++#undef CONFIG_SYS_NO_FLASH ++#define CFG_FLASH_CFI_DRIVER ++#define CFG_FLASH_CFI ++#define CFG_MAX_FLASH_BANKS 1 /* max number of flash banks */ ++#define CFG_FLASH_SECT_SZ 0x10000 /* 64KB sect size AMD Flash */ ++#define CONFIG_ENV_OFFSET (CFG_FLASH_SECT_SZ*3) ++#define CFG_FLASH_BASE DAVINCI_ASYNC_EMIF_DATA_CE2_BASE ++#define PHYS_FLASH_SIZE 0x2000000 /* Flash size 32MB */ ++#define CFG_MAX_FLASH_SECT (PHYS_FLASH_SIZE/CFG_FLASH_SECT_SZ) ++#define CONFIG_ENV_SECT_SIZE CFG_FLASH_SECT_SZ /* Env sector Size */ ++#endif ++ ++#ifdef CFG_USE_SPIFLASH ++#undef CONFIG_ENV_IS_IN_FLASH ++#undef CONFIG_ENV_IS_IN_NAND ++#define CONFIG_ENV_IS_IN_SPI_FLASH ++#define CONFIG_ENV_SIZE SZ_16K ++#define CONFIG_ENV_OFFSET SZ_256K ++#define CONFIG_ENV_SECT_SIZE SZ_4K ++#define CONFIG_SYS_NO_FLASH ++#define CONFIG_SPI ++#define CONFIG_SPI_FLASH ++#define CONFIG_SPI_FLASH_WINBOND ++#define CONFIG_DAVINCI_SPI ++#define CFG_SPI_BASE DAVINCI_SPI0_BASE ++#define CFG_SPI_CLK clk_get(DAVINCI_SPI0_CLKID) ++#define CONFIG_SF_DEFAULT_SPEED 50000000 ++#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED ++#endif ++ ++ ++/*==============================*/ ++/* U-Boot general configuration */ ++/*==============================*/ ++#undef CONFIG_USE_IRQ /* No IRQ/FIQ in U-Boot */ ++#define CONFIG_MISC_INIT_R ++#undef CONFIG_BOOTDELAY ++#define CONFIG_BOOTFILE "uImage" /* Boot file name */ ++#define CONFIG_SYS_PROMPT "U-Boot > " /* Monitor Command Prompt */ ++#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print buffer sz */ ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ ++#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_MEMTEST_START + 0x700000) /* default Linux kernel load address */ ++#define CONFIG_VERSION_VARIABLE ++#define CONFIG_AUTO_COMPLETE /* Won't work with hush so far, may be later */ ++#define CONFIG_SYS_HUSH_PARSER ++#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " ++#define CONFIG_CMDLINE_EDITING ++#define CONFIG_SYS_LONGHELP ++#define CONFIG_CRC32_VERIFY ++#define CONFIG_MX_CYCLIC ++ ++/*===================*/ ++/* Linux Information */ ++/*===================*/ ++#define LINUX_BOOT_PARAM_ADDR (CONFIG_SYS_MEMTEST_START + 0x100) ++#define CONFIG_CMDLINE_TAG ++#define CONFIG_SETUP_MEMORY_TAGS ++#define CONFIG_BOOTARGS "mem=32M console=ttyS0,115200n8 root=/dev/mtdblock/2 rw noinitrd ip=dhcp" ++#define CONFIG_BOOTCOMMAND "" ++#define CONFIG_BOOTDELAY 3 ++ ++/*=================*/ ++/* U-Boot commands */ ++/*=================*/ ++#include <config_cmd_default.h> ++#define CONFIG_CMD_ENV ++#define CONFIG_CMD_ASKENV ++#define CONFIG_CMD_DHCP ++#define CONFIG_CMD_DIAG ++#define CONFIG_CMD_MII ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_SAVES ++#define CONFIG_CMD_MEMORY ++#undef CONFIG_CMD_BDI ++#undef CONFIG_CMD_FPGA ++#undef CONFIG_CMD_SETGETDCR ++#define CONFIG_CMD_EEPROM ++ ++#ifdef CONFIG_SYS_USE_NAND ++#undef CONFIG_CMD_FLASH ++#undef CONFIG_CMD_IMLS ++#define CONFIG_CMD_NAND ++#endif ++ ++#ifdef CFG_USE_SPIFLASH ++#undef CONFIG_CMD_IMLS ++#undef CONFIG_CMD_FLASH ++#define CONFIG_CMD_SF ++#endif ++ ++#if !defined(CONFIG_SYS_USE_NAND) && !defined(CONFIG_SYS_USE_NOR) && !defined(CFG_USE_SPIFLASH) ++#define CFG_ENV_IS_NOWHERE ++#define CONFIG_SYS_NO_FLASH ++#define CONFIG_ENV_SIZE SZ_16K ++#undef CONFIG_CMD_IMLS ++#undef CONFIG_CMD_FLASH ++#undef CONFIG_CMD_ENV ++#endif ++ ++#endif /* __CONFIG_H */ +Index: u-boot-2009.01-primus/board/da850/da850-evm/Makefile +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/board/da850/da850-evm/Makefile +@@ -0,0 +1,52 @@ ++# ++# (C) Copyright 2000, 2001, 2002 ++# Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++# ++# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++# ++# 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).a ++ ++COBJS := dv_board.o ++SOBJS := board_init.o ++ ++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(COBJS)) ++SOBJS := $(addprefix $(obj),$(SOBJS)) ++ ++$(LIB): $(obj).depend $(OBJS) $(SOBJS) ++ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) ++ ++clean: ++ rm -f $(SOBJS) $(OBJS) ++ ++distclean: clean ++ rm -f $(LIB) core *.bak *~ .depend ++ ++######################################################################### ++# This is for $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +Index: u-boot-2009.01-primus/board/da850/da850-evm/board_init.S +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/board/da850/da850-evm/board_init.S +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Board-specific low level initialization code. Called at the very end ++ * of cpu/arm926ejs/davinci/lowlevel_init.S. Just returns if there is no ++ * initialization required. ++ * ++ * 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> ++ ++.globl dv_board_init ++dv_board_init: ++ ++ mov pc, lr +Index: u-boot-2009.01-primus/board/da850/da850-evm/config.mk +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/board/da850/da850-evm/config.mk +@@ -0,0 +1,30 @@ ++# ++# (C) Copyright 2002 ++# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> ++# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> ++# ++# (C) Copyright 2003 ++# Texas Instruments, <www.ti.com> ++# Swaminathan <swami.iyer@ti.com> ++# ++# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++# ++# (C) Copyright 2008 ++# Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> ++# ++# Texas Instruments DA8xx EVM board (ARM925EJS) cpu ++# see http://www.ti.com/ for more information on Texas Instruments ++# ++# DA8xx EVM has 1 bank of 64 MB SDRAM (2 16Meg x16 chips). ++# Physical Address: ++# C000'0000 to C400'0000 ++# ++# Linux-Kernel is expected to be at C000'8000, entry C000'8000 ++# (mem base + reserved) ++# ++# we load ourself to C108 '0000 ++# ++# ++ ++#Provide at least 16MB spacing between us and the Linux Kernel image ++TEXT_BASE = 0xC1080000 +Index: u-boot-2009.01-primus/board/da850/da850-evm/dv_board.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/board/da850/da850-evm/dv_board.c +@@ -0,0 +1,232 @@ ++/* ++ * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> ++ * ++ * Modified for DA8xx EVM. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Parts are shamelessly stolen from various TI sources, original copyright ++ * follows: ++ * ----------------------------------------------------------------- ++ * ++ * Copyright (C) 2004 Texas Instruments. ++ * ++ * ---------------------------------------------------------------------------- ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ */ ++ ++#include <common.h> ++#include <i2c.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/emac_defs.h> ++ ++#define MACH_TYPE_DA850_EVM 1781 ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++extern void timer_init(void); ++extern int eth_hw_init(void); ++ ++/* Works on Always On power domain only (no PD argument) */ ++void lpsc_on(unsigned int id) ++{ ++ dv_reg_p mdstat, mdctl, ptstat, ptcmd; ++ ++ if (id >= 64) ++ return; ++ ++ if(id < 32) { ++ mdstat = REG_P(PSC0_MDSTAT + (id * 4)); ++ mdctl = REG_P(PSC0_MDCTL + (id * 4)); ++ ptstat = REG_P(PSC0_PTSTAT); ++ ptcmd = REG_P(PSC0_PTCMD); ++ } else { ++ id -= 32; ++ mdstat = REG_P(PSC1_MDSTAT + (id * 4)); ++ mdctl = REG_P(PSC1_MDCTL + (id * 4)); ++ ptstat = REG_P(PSC1_PTSTAT); ++ ptcmd = REG_P(PSC1_PTCMD); ++ } ++ ++ while (*ptstat & 0x01) {;} ++ ++ if ((*mdstat & 0x1f) == 0x03) ++ return; /* Already on and enabled */ ++ ++ *mdctl |= 0x03; ++ ++ /* Special treatment for some modules as for sprue14 p.7.4.2 */ ++ /* TBD: Confirm if such cases exist for Primus */ ++ if (0) ++ *mdctl |= 0x200; ++ ++ *ptcmd = 0x01; ++ ++ while (*ptstat & 0x01) {;} ++ while ((*mdstat & 0x1f) != 0x03) {;} /* Probably an overkill... */ ++} ++ ++int board_init(void) ++{ ++ ++ dv_reg_p intc; ++ ++ /*-------------------------------------------------------* ++ * Mask all IRQs by clearing the global enable and setting ++ * the enable clear for all the 90 interrupts. This code is ++ * also included in low level init. Including it here in case ++ * low level init is skipped. Not removing it from low level ++ * init in case some of the low level init code generates ++ * interrupts... Not expected... but you never know... ++ *-------------------------------------------------------*/ ++ ++#ifndef CONFIG_USE_IRQ ++ intc = REG_P(INTC_GLB_EN); ++ intc[0] = 0; ++ ++ intc = REG_P(INTC_HINT_EN); ++ intc[0] = 0; ++ intc[1] = 0; ++ intc[2] = 0; ++ ++ intc = REG_P(INTC_EN_CLR0); ++ intc[0] = 0xFFFFFFFF; ++ intc[1] = 0xFFFFFFFF; ++ intc[2] = 0xFFFFFFFF; ++#endif ++ ++ /* arch number of the board */ ++ gd->bd->bi_arch_number = MACH_TYPE_DA850_EVM; ++ ++ /* address of boot parameters */ ++ gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; ++ ++ /* setup the SUSPSRC for ARM to control emulation suspend */ ++ REG(SUSPSRC) &= ~( (1 << 27) /* Timer0 */ ++ | (1 << 21) /* SPI0 */ ++ | (1 << 18) /* UART0 */ ++ | (1 << 5) /* EMAC */ ++ | (1 << 16) /* I2C0 */ ++ ); ++ ++ /* Power on required peripherals ++ * ARM does not have acess by default to PSC0 and PSC1 ++ * assuming here that the DSP bootloader has set the IOPU ++ * such that PSC access is available to ARM ++ */ ++ lpsc_on(DAVINCI_LPSC_AEMIF); /* NAND, NOR */ ++ lpsc_on(DAVINCI_LPSC_SPI0); /* Serial Flash */ ++ lpsc_on(DAVINCI_LPSC_EMAC); /* image download */ ++ lpsc_on(DAVINCI_LPSC_UART0); /* console */ ++ lpsc_on(DAVINCI_LPSC_GPIO); ++ ++ /* Pin Muxing support */ ++ ++ /* write the kick registers to unlock the PINMUX registers */ ++ REG(KICK0) = 0x83e70b13; /* Kick0 unlock */ ++ REG(KICK1) = 0x95a4f1e0; /* Kick1 unlock */ ++ ++#ifdef CONFIG_SPI_FLASH ++ /* SPI0 */ ++ REG(PINMUX3) &= 0xFFFF0000; ++ REG(PINMUX3) |= 0x00001111; ++ REG(PINMUX4) &= 0xFFFFFF0F; ++ REG(PINMUX4) |= 0x00000010; ++#endif ++ ++#ifdef CONFIG_DRIVER_TI_EMAC ++ /* RMII clock is sourced externally */ ++ REG(PINMUX15) &= 0xFFFFFFF0; ++ REG(PINMUX14) &= 0x000000FF; ++ REG(PINMUX14) |= 0x88888800; ++ REG(PINMUX15) &= 0xFFFFFF0F; ++ REG(PINMUX15) |= 0x00000080; ++ REG(PINMUX4) &= 0xFFFFFF00; ++ REG(PINMUX4) |= 0x00000088; ++#endif ++ ++ /* Async EMIF */ ++#if defined(CFG_USE_NAND) || defined(CFG_USE_NOR) ++ REG(PINMUX6) = 0x11111111; ++ REG(PINMUX7) = 0x11111111; ++ REG(PINMUX8) = 0x11111111; ++ REG(PINMUX9) = 0x11111111; ++ REG(PINMUX10) = 0x11111111; ++ REG(PINMUX11) = 0x11111111; ++ REG(PINMUX12) = 0x11111111; ++ REG(PINMUX5) &= 0x00FFFFFF; ++ REG(PINMUX5) |= 0x11000000; ++#endif ++ ++ /* UART0 Muxing and enabling */ ++ REG(PINMUX3) &= 0x0000FFFF; ++ REG(PINMUX3) |= 0x22220000; ++ ++ REG(DAVINCI_UART0_BASE + 0x30) = 0xE001; ++ ++ /* I2C muxing */ ++ REG(PINMUX4) &= 0xFFFF00FF; ++ REG(PINMUX4) |= 0x00002200; ++ ++ /* write the kick registers to lock the PINMUX registers */ ++ REG(KICK0) = 0x0; /* Kick0 lock */ ++ REG(KICK1) = 0x0; /* Kick1 lock */ ++ ++ return(0); ++} ++ ++int misc_init_r (void) ++{ ++ u_int8_t tmp[20], buf[10]; ++ int i; ++ ++ printf ("ARM Clock : %d Hz\n", clk_get(DAVINCI_ARM_CLKID)); ++ ++ /* Set Ethernet MAC address from EEPROM */ ++ if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0x7f00, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, 6)) { ++ printf("\nEEPROM @ 0x%02x read FAILED!!!\n", CONFIG_SYS_I2C_EEPROM_ADDR); ++ } else { ++ tmp[0] = 0xff; ++ for (i = 0; i < 6; i++) ++ tmp[0] &= buf[i]; ++ ++ if ((tmp[0] != 0xff) && (getenv("ethaddr") == NULL)) { ++ sprintf((char *)&tmp[0], "%02x:%02x:%02x:%02x:%02x:%02x", ++ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); ++ setenv("ethaddr", (char *)&tmp[0]); ++ } ++ } ++ ++ tmp[0] = 0x01; ++ tmp[1] = 0x23; ++ if(i2c_write(0x5f, 0, 0, tmp, 2)) { ++ printf("Ethernet switch start failed!\n"); ++ } ++ ++ if (!eth_hw_init()) { ++ printf("Error: Ethernet init failed!\n"); ++ } ++ ++ return(0); ++} ++ ++int dram_init(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++ ++ return(0); ++} +Index: u-boot-2009.01-primus/board/da850/da850-evm/u-boot.lds +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/board/da850/da850-evm/u-boot.lds +@@ -0,0 +1,52 @@ ++/* ++ * (C) Copyright 2002 ++ * Gary Jennejohn, DENX Software Engineering, <gj@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 ++ */ ++ ++OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") ++OUTPUT_ARCH(arm) ++ENTRY(_start) ++SECTIONS ++{ ++ . = 0x00000000; ++ . = ALIGN(4); ++ .text : ++ { ++ cpu/arm926ejs/start.o (.text) ++ *(.text) ++ } ++ . = ALIGN(4); ++ .rodata : { *(.rodata) } ++ . = ALIGN(4); ++ .data : { *(.data) } ++ . = ALIGN(4); ++ .got : { *(.got) } ++ ++ . = .; ++ __u_boot_cmd_start = .; ++ .u_boot_cmd : { *(.u_boot_cmd) } ++ __u_boot_cmd_end = .; ++ ++ . = ALIGN(4); ++ __bss_start = .; ++ .bss (NOLOAD) : { *(.bss) } ++ _end = .; ++} +Index: u-boot-2009.01-primus/cpu/arm926ejs/da850/Makefile +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/cpu/arm926ejs/da850/Makefile +@@ -0,0 +1,49 @@ ++# ++# (C) Copyright 2000-2006 ++# Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++# ++# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++# ++# See file CREDITS for list of people who contributed to this ++# project. ++# ++# This program is free software; you can redistribute it and/or ++# modify it under the terms of the GNU General Public License as ++# published by the Free Software Foundation; either version 2 of ++# the License, or (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++# MA 02111-1307 USA ++# ++ ++include $(TOPDIR)/config.mk ++ ++LIB = $(obj)lib$(SOC).a ++ ++COBJS = timer.o ether.o nand.o clock.o i2c.o ++SOBJS = lowlevel_init.o reset.o ++ ++SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) ++START := $(addprefix $(obj),$(START)) ++ ++all: $(obj).depend $(LIB) ++ ++$(LIB): $(OBJS) ++ $(AR) $(ARFLAGS) $@ $(OBJS) ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +Index: u-boot-2009.01-primus/cpu/arm926ejs/da850/clock.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/cpu/arm926ejs/da850/clock.c +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> ++ * ++ * DA8xx clock module ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ */ ++ ++#include <common.h> ++#include <asm/arch/hardware.h> ++ ++dv_reg_p sysdiv[9] = { ++ PLL0_DIV1, PLL0_DIV2, PLL0_DIV3, PLL0_DIV4, PLL0_DIV5, PLL0_DIV6, ++ PLL0_DIV7, PLL0_DIV8, PLL0_DIV9 }; ++ ++int clk_get(unsigned int id) ++{ ++ int pre_div = (REG(PLL0_PREDIV) & 0xff) + 1; ++ int pllm = REG(PLL0_PLLM) + 1; ++ int post_div = (REG(PLL0_POSTDIV) & 0xff) + 1; ++ int pll_out = CFG_OSCIN_FREQ; ++ ++ if(id == DAVINCI_AUXCLK_CLKID) ++ goto out; ++ ++ /* Lets keep this simple. Combining operations can result in ++ * unexpected approximations ++ */ ++ pll_out /= pre_div; ++ pll_out *= pllm; ++ ++ if(id == DAVINCI_PLLM_CLKID) ++ goto out; ++ ++ pll_out /= post_div; ++ ++ if(id == DAVINCI_PLLC_CLKID) ++ goto out; ++ ++ pll_out /= (REG(sysdiv[id - 1]) & 0xff) + 1; ++ ++out: ++ return pll_out; ++} +Index: u-boot-2009.01-primus/cpu/arm926ejs/da850/ether.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/cpu/arm926ejs/da850/ether.c +@@ -0,0 +1,667 @@ ++/* ++ * Ethernet driver for TI TMS320DM644x (DaVinci) chips. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright ++ * follows: ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * dm644x_emac.c ++ * ++ * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM ++ * ++ * Copyright (C) 2005 Texas Instruments. ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ ++ * Modifications: ++ * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot. ++ * ver 1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors ++ * ++ */ ++#include <common.h> ++#include <command.h> ++#include <net.h> ++#include <miiphy.h> ++#include <asm/arch/emac_defs.h> ++ ++#ifdef CONFIG_DRIVER_TI_EMAC ++ ++#ifdef CONFIG_CMD_NET ++ ++unsigned int emac_dbg = 0; ++#define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args) ++ ++/* Internal static functions */ ++static int dm644x_eth_hw_init (void); ++static int dm644x_eth_open (void); ++static int dm644x_eth_close (void); ++static int dm644x_eth_send_packet (volatile void *packet, int length); ++static int dm644x_eth_rcv_packet (void); ++static void dm644x_eth_mdio_enable(void); ++ ++static int gen_init_phy(int phy_addr); ++static int gen_is_phy_connected(int phy_addr); ++static int gen_get_link_speed(int phy_addr); ++static int gen_auto_negotiate(int phy_addr); ++ ++/* Wrappers exported to the U-Boot proper */ ++int eth_hw_init(void) ++{ ++ return(dm644x_eth_hw_init()); ++} ++ ++int eth_init(bd_t * bd) ++{ ++ return(dm644x_eth_open()); ++} ++ ++void eth_halt(void) ++{ ++ dm644x_eth_close(); ++} ++ ++int eth_send(volatile void *packet, int length) ++{ ++ return(dm644x_eth_send_packet(packet, length)); ++} ++ ++int eth_rx(void) ++{ ++ return(dm644x_eth_rcv_packet()); ++} ++ ++void eth_mdio_enable(void) ++{ ++ dm644x_eth_mdio_enable(); ++} ++/* End of wrappers */ ++ ++/* dm644x_eth_mac_addr[0] goes out on the wire first */ ++ ++static u_int8_t dm644x_eth_mac_addr[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0x00 }; ++ ++/* ++ * This function must be called before emac_open() if you want to override ++ * the default mac address. ++ */ ++void dm644x_eth_set_mac_addr(const u_int8_t *addr) ++{ ++ int i; ++ ++ for (i = 0; i < sizeof (dm644x_eth_mac_addr); i++) { ++ dm644x_eth_mac_addr[i] = addr[i]; ++ } ++} ++ ++/* EMAC Addresses */ ++static volatile emac_regs *adap_emac = (emac_regs *)EMAC_BASE_ADDR; ++static volatile ewrap_regs *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR; ++static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR; ++ ++/* EMAC descriptors */ ++static volatile emac_desc *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE); ++static volatile emac_desc *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE); ++static volatile emac_desc *emac_rx_active_head = 0; ++static volatile emac_desc *emac_rx_active_tail = 0; ++static int emac_rx_queue_active = 0; ++ ++/* Receive packet buffers */ ++static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; ++ ++/* PHY address for a discovered PHY (0xff - not found) */ ++static volatile u_int8_t active_phy_addr = 0xff; ++ ++static int no_phy_init (int phy_addr) { return(1); } ++static int no_phy_is_connected (int phy_addr) { return(1); } ++static int no_phy_get_link_speed (int phy_addr) { return(1); } ++static int no_phy_auto_negotiate (int phy_addr) { return(1); } ++phy_t phy = { ++ .init = no_phy_init, ++ .is_phy_connected = no_phy_is_connected, ++ .get_link_speed = no_phy_get_link_speed, ++ .auto_negotiate = no_phy_auto_negotiate ++}; ++ ++static void dm644x_eth_mdio_enable(void) ++{ ++ u_int32_t clkdiv; ++ ++ clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; ++ ++ adap_mdio->CONTROL = (clkdiv & 0xff) | ++ MDIO_CONTROL_ENABLE | ++ MDIO_CONTROL_FAULT | ++ MDIO_CONTROL_FAULT_ENABLE; ++ ++ while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;} ++} ++ ++/* ++ * Tries to find an active connected PHY. Returns 1 if address if found. ++ * If no active PHY found returns 0. If more than one active PHY (switch) ++ * returns 2 ++ * Sets active_phy_addr variable when returns 1. ++ */ ++static int dm644x_eth_phy_detect(void) ++{ ++ u_int32_t phy_act_state; ++ int i; ++ ++ active_phy_addr = 0xff; ++ ++ if ((phy_act_state = adap_mdio->ALIVE) == 0) ++ return(0); /* No active PHYs */ ++ ++ debug_emac("dm644x_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state); ++ ++ for (i = 0; i < 32; i++) { ++ if (phy_act_state & (1 << i)) { ++ if (phy_act_state & ~(1 << i)) ++ return(2); /* More than one PHY */ ++ else { ++ active_phy_addr = i; ++ return(1); ++ } ++ } ++ } ++ ++ return(0); /* Just to make GCC happy */ ++} ++ ++ ++/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */ ++int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) ++{ ++ int tmp; ++ ++ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} ++ ++ adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO | ++ MDIO_USERACCESS0_WRITE_READ | ++ ((reg_num & 0x1f) << 21) | ++ ((phy_addr & 0x1f) << 16); ++ ++ /* Wait for command to complete */ ++ while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;} ++ ++ if (tmp & MDIO_USERACCESS0_ACK) { ++ *data = tmp & 0xffff; ++ return(1); ++ } ++ ++ *data = -1; ++ return(0); ++} ++ ++/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */ ++int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) ++{ ++ ++ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} ++ ++ adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO | ++ MDIO_USERACCESS0_WRITE_WRITE | ++ ((reg_num & 0x1f) << 21) | ++ ((phy_addr & 0x1f) << 16) | ++ (data & 0xffff); ++ ++ /* Wait for command to complete */ ++ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} ++ ++ return(1); ++} ++ ++/* PHY functions for a generic PHY */ ++static int gen_init_phy(int phy_addr) ++{ ++ int ret = 1; ++ ++ if (gen_get_link_speed(phy_addr)) { ++ /* Try another time */ ++ ret = gen_get_link_speed(phy_addr); ++ } ++ ++ return(ret); ++} ++ ++static int gen_is_phy_connected(int phy_addr) ++{ ++ u_int16_t dummy; ++ ++ return(dm644x_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy)); ++} ++ ++static int gen_get_link_speed(int phy_addr) ++{ ++ u_int16_t tmp; ++ ++ if (dm644x_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04)) ++ return(1); ++ ++ return(0); ++} ++ ++static int gen_auto_negotiate(int phy_addr) ++{ ++ u_int16_t tmp; ++ ++ if (!dm644x_eth_phy_read(phy_addr, PHY_BMCR, &tmp)) ++ return(0); ++ ++ /* Restart Auto_negotiation */ ++ tmp |= PHY_BMCR_AUTON; ++ dm644x_eth_phy_write(phy_addr, PHY_BMCR, tmp); ++ ++ /*check AutoNegotiate complete */ ++ udelay (10000); ++ if (!dm644x_eth_phy_read(phy_addr, PHY_BMSR, &tmp)) ++ return(0); ++ ++ if (!(tmp & PHY_BMSR_AUTN_COMP)) ++ return(0); ++ ++ return(gen_get_link_speed(phy_addr)); ++} ++/* End of generic PHY functions */ ++ ++ ++#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) ++static int dm644x_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value) ++{ ++ return(dm644x_eth_phy_read(addr, reg, value) ? 0 : 1); ++} ++ ++static int dm644x_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value) ++{ ++ return(dm644x_eth_phy_write(addr, reg, value) ? 0 : 1); ++} ++ ++int dm644x_eth_miiphy_initialize(bd_t *bis) ++{ ++ miiphy_register(phy.name, dm644x_mii_phy_read, dm644x_mii_phy_write); ++ ++ return(1); ++} ++#endif ++ ++/* ++ * This function initializes the emac hardware. It does NOT initialize ++ * EMAC modules power or pin multiplexors, that is done by board_init() ++ * much earlier in bootup process. Returns 1 on success, 0 otherwise. ++ */ ++static int dm644x_eth_hw_init(void) ++{ ++ u_int32_t phy_id; ++ u_int16_t tmp; ++ int i, ret; ++ ++ /* The RMII clock can be sources internally through the SYSCLK7 ++ * or can come externally through a dedicated pin. This selection is ++ * controlled by PinMux9[21]. PinMux registers are off-limits for ARM. ++ * In short, we just assume there is a 50MHz RMII clock available. ++ */ ++ ++ dm644x_eth_mdio_enable(); ++ ++ for (i = 0; i < 256; i++) { ++ if (adap_mdio->ALIVE) ++ break; ++ udelay(1000); ++ } ++ ++ if (i >= 256) { ++ printf("No ETH PHY detected!!!\n"); ++ return(0); ++ } ++ ++ /* Find if a PHY is connected and get it's address */ ++ ret = dm644x_eth_phy_detect(); ++ ++ if (ret == 2) { ++ printf("More than one PHY detected.\n"); ++ return(1); ++ } else if(ret == 0) ++ return(0); ++ ++ /* Get PHY ID and initialize phy_ops for a detected PHY */ ++ if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) { ++ active_phy_addr = 0xff; ++ return(0); ++ } ++ ++ phy_id = (tmp << 16) & 0xffff0000; ++ ++ if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) { ++ active_phy_addr = 0xff; ++ return(0); ++ } ++ ++ phy_id |= tmp & 0x0000ffff; ++ ++ switch (phy_id) { ++ default: ++ sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr); ++ phy.init = gen_init_phy; ++ phy.is_phy_connected = gen_is_phy_connected; ++ phy.get_link_speed = gen_get_link_speed; ++ phy.auto_negotiate = gen_auto_negotiate; ++ } ++ ++ return(1); ++} ++ ++ ++/* Eth device open */ ++static int dm644x_eth_open(void) ++{ ++ dv_reg_p addr; ++ u_int32_t clkdiv, cnt; ++ volatile emac_desc *rx_desc; ++ int i; ++ ++ debug_emac("+ emac_open\n"); ++ ++ /* Reset EMAC module and disable interrupts in wrapper */ ++ adap_emac->SOFTRESET = 1; ++ while (adap_emac->SOFTRESET != 0) {;} ++ adap_ewrap->SOFTRESET = 1; ++ while (adap_ewrap->SOFTRESET != 0) {;} ++ ++ adap_ewrap->C0RXEN = adap_ewrap->C1RXEN = adap_ewrap->C2RXEN = 0; ++ adap_ewrap->C0TXEN = adap_ewrap->C1TXEN = adap_ewrap->C2TXEN = 0; ++ adap_ewrap->C0MISCEN = adap_ewrap->C1MISCEN = adap_ewrap->C2MISCEN = 0; ++ ++ rx_desc = emac_rx_desc; ++ ++ adap_emac->TXCONTROL = 0x01; ++ adap_emac->RXCONTROL = 0x01; ++ ++ /* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */ ++ /* Using channel 0 only - other channels are disabled */ ++ for (i = 0; i < 8; i++) { ++ adap_emac->MACINDEX = i; ++ adap_emac->MACADDRHI = ++ (dm644x_eth_mac_addr[3] << 24) | /* bits 23-16 */ ++ (dm644x_eth_mac_addr[2] << 16) | /* bits 31-24 */ ++ (dm644x_eth_mac_addr[1] << 8) | /* bits 39-32 */ ++ (dm644x_eth_mac_addr[0]); /* bits 47-40 */ ++ adap_emac->MACADDRLO = ++ (dm644x_eth_mac_addr[5] << 8) | /* bits 8-0*/ ++ (dm644x_eth_mac_addr[4]) | (1 << 19) | (1 << 20); /* bits 8-0 */ ++ } ++ ++ adap_emac->MACHASH1 = 0; ++ adap_emac->MACHASH2 = 0; ++ ++ /* Set source MAC address - REQUIRED for pause frames */ ++ adap_emac->MACSRCADDRHI = ++ (dm644x_eth_mac_addr[3] << 24) | /* bits 23-16 */ ++ (dm644x_eth_mac_addr[2] << 16) | /* bits 31-24 */ ++ (dm644x_eth_mac_addr[1] << 8) | /* bits 39-32 */ ++ (dm644x_eth_mac_addr[0]); /* bits 47-40 */ ++ adap_emac->MACSRCADDRLO = ++ (dm644x_eth_mac_addr[5] << 8) | /* bits 8-0 */ ++ (dm644x_eth_mac_addr[4]); /* bits 15-8 */ ++ ++ /* Set DMA 8 TX / 8 RX Head pointers to 0 */ ++ addr = &adap_emac->TX0HDP; ++ for(cnt = 0; cnt < 16; cnt++) ++ *addr++ = 0; ++ ++ addr = &adap_emac->TX0CP; ++ for(cnt = 0; cnt < 16; cnt++) ++ *addr++ = 0; ++ ++ /* Clear Statistics (do this before setting MacControl register) */ ++ addr = &adap_emac->RXGOODFRAMES; ++ for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++) ++ *addr++ = 0; ++ ++ /* No multicast addressing */ ++ adap_emac->MACHASH1 = 0; ++ adap_emac->MACHASH2 = 0; ++ ++ /* Create RX queue and set receive process in place */ ++ emac_rx_active_head = emac_rx_desc; ++ for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) { ++ rx_desc->next = (u_int32_t)(rx_desc + 1); ++ rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; ++ rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; ++ rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; ++ rx_desc++; ++ } ++ ++ /* Set the last descriptor's "next" parameter to 0 to end the RX desc list */ ++ rx_desc--; ++ rx_desc->next = 0; ++ emac_rx_active_tail = rx_desc; ++ emac_rx_queue_active = 1; ++ ++ /* Enable TX/RX */ ++ adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE; ++ adap_emac->RXBUFFEROFFSET = 0; ++ ++ /* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */ ++ adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN; ++ ++ /* Enable ch 0 only */ ++ adap_emac->RXUNICASTSET = 0x01; ++ ++ /* Enable MII interface and Full duplex mode */ ++ adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE) | EMAC_MACCONTROL_RMIISPEED_100; ++ ++ /* Init MDIO & get link state */ ++ clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; ++ adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT); ++ ++ if (!phy.get_link_speed(active_phy_addr)) ++ return(0); ++ ++ /* Start receive process */ ++ adap_emac->RX0HDP = (u_int32_t)emac_rx_desc; ++ ++ debug_emac("- emac_open\n"); ++ ++ return(1); ++} ++ ++/* EMAC Channel Teardown */ ++static void dm644x_eth_ch_teardown(int ch) ++{ ++ dv_reg dly = 0xff; ++ dv_reg cnt; ++ ++ debug_emac("+ emac_ch_teardown\n"); ++ ++ if (ch == EMAC_CH_TX) { ++ /* Init TX channel teardown */ ++ adap_emac->TXTEARDOWN = 1; ++ for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) { ++ /* Wait here for Tx teardown completion interrupt to occur ++ * Note: A task delay can be called here to pend rather than ++ * occupying CPU cycles - anyway it has been found that teardown ++ * takes very few cpu cycles and does not affect functionality */ ++ dly--; ++ udelay(1); ++ if (dly == 0) ++ break; ++ } ++ adap_emac->TX0CP = cnt; ++ adap_emac->TX0HDP = 0; ++ } else { ++ /* Init RX channel teardown */ ++ adap_emac->RXTEARDOWN = 1; ++ for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) { ++ /* Wait here for Rx teardown completion interrupt to occur ++ * Note: A task delay can be called here to pend rather than ++ * occupying CPU cycles - anyway it has been found that teardown ++ * takes very few cpu cycles and does not affect functionality */ ++ dly--; ++ udelay(1); ++ if (dly == 0) ++ break; ++ } ++ adap_emac->RX0CP = cnt; ++ adap_emac->RX0HDP = 0; ++ } ++ ++ debug_emac("- emac_ch_teardown\n"); ++} ++ ++/* Eth device close */ ++static int dm644x_eth_close(void) ++{ ++ debug_emac("+ emac_close\n"); ++ ++ dm644x_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */ ++ dm644x_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */ ++ ++ /* Reset EMAC module and disable interrupts in wrapper */ ++ adap_emac->SOFTRESET = 1; ++ adap_ewrap->SOFTRESET = 1; ++ ++ adap_ewrap->C0RXEN = adap_ewrap->C1RXEN = adap_ewrap->C2RXEN = 0; ++ adap_ewrap->C0TXEN = adap_ewrap->C1TXEN = adap_ewrap->C2TXEN = 0; ++ adap_ewrap->C0MISCEN = adap_ewrap->C1MISCEN = adap_ewrap->C2MISCEN = 0; ++ ++ debug_emac("- emac_close\n"); ++ return(1); ++} ++ ++static int tx_send_loop = 0; ++ ++/* ++ * This function sends a single packet on the network and returns ++ * positive number (number of bytes transmitted) or negative for error ++ */ ++static int dm644x_eth_send_packet(volatile void *packet, int length) ++{ ++ int ret_status = -1; ++ tx_send_loop = 0; ++ ++ /* Return error if no link */ ++ if (!phy.get_link_speed(active_phy_addr)) ++ { ++ printf("WARN: emac_send_packet: No link\n"); ++ return (ret_status); ++ } ++ ++ /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */ ++ if (length < EMAC_MIN_ETHERNET_PKT_SIZE) ++ { ++ length = EMAC_MIN_ETHERNET_PKT_SIZE; ++ } ++ ++ /* Populate the TX descriptor */ ++ emac_tx_desc->next = 0; ++ emac_tx_desc->buffer = (u_int8_t *)packet; ++ emac_tx_desc->buff_off_len = (length & 0xffff); ++ emac_tx_desc->pkt_flag_len = ((length & 0xffff) | ++ EMAC_CPPI_SOP_BIT | ++ EMAC_CPPI_OWNERSHIP_BIT | ++ EMAC_CPPI_EOP_BIT); ++ /* Send the packet */ ++ adap_emac->TX0HDP = (unsigned int)emac_tx_desc; ++ ++ /* Wait for packet to complete or link down */ ++ while (1) { ++ if (!phy.get_link_speed(active_phy_addr)) { ++ dm644x_eth_ch_teardown(EMAC_CH_TX); ++ return (ret_status); ++ } ++ if (adap_emac->TXINTSTATRAW & 0x01) { ++ ret_status = length; ++ break; ++ } ++ tx_send_loop++; ++ } ++ ++ return(ret_status); ++} ++ ++/* ++ * This function handles receipt of a packet from the network ++ */ ++static int dm644x_eth_rcv_packet(void) ++{ ++ volatile emac_desc *rx_curr_desc; ++ volatile emac_desc *curr_desc; ++ volatile emac_desc *tail_desc; ++ int status, ret = -1; ++ ++ rx_curr_desc = emac_rx_active_head; ++ status = rx_curr_desc->pkt_flag_len; ++ if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) { ++ if (status & EMAC_CPPI_RX_ERROR_FRAME) { ++ /* Error in packet - discard it and requeue desc */ ++ printf("WARN: emac_rcv_pkt: Error in packet\n"); ++ } else { ++ NetReceive(rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff)); ++ ret = rx_curr_desc->buff_off_len & 0xffff; ++ } ++ ++ /* Ack received packet descriptor */ ++ adap_emac->RX0CP = (unsigned int)rx_curr_desc; ++ curr_desc = rx_curr_desc; ++ emac_rx_active_head = (volatile emac_desc *)rx_curr_desc->next; ++ ++ if (status & EMAC_CPPI_EOQ_BIT) { ++ if (emac_rx_active_head) { ++ adap_emac->RX0HDP = (unsigned int)emac_rx_active_head; ++ } else { ++ emac_rx_queue_active = 0; ++ printf("INFO:emac_rcv_packet: RX Queue not active\n"); ++ } ++ } ++ ++ /* Recycle RX descriptor */ ++ rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; ++ rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; ++ rx_curr_desc->next = 0; ++ ++ if (emac_rx_active_head == 0) { ++ printf("INFO: emac_rcv_pkt: active queue head = 0\n"); ++ emac_rx_active_head = curr_desc; ++ emac_rx_active_tail = curr_desc; ++ if (emac_rx_queue_active != 0) { ++ adap_emac->RX0HDP = (unsigned int)emac_rx_active_head; ++ printf("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n"); ++ emac_rx_queue_active = 1; ++ } ++ } else { ++ tail_desc = emac_rx_active_tail; ++ emac_rx_active_tail = curr_desc; ++ tail_desc->next = (unsigned int)curr_desc; ++ status = tail_desc->pkt_flag_len; ++ if (status & EMAC_CPPI_EOQ_BIT) { ++ adap_emac->RX0HDP = (unsigned int)curr_desc; ++ status &= ~EMAC_CPPI_EOQ_BIT; ++ tail_desc->pkt_flag_len = status; ++ } ++ } ++ return(ret); ++ } ++ return(0); ++} ++ ++#endif /* CONFIG_CMD_NET */ ++ ++#endif /* CONFIG_DRIVER_TI_EMAC */ +Index: u-boot-2009.01-primus/cpu/arm926ejs/da850/i2c.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/cpu/arm926ejs/da850/i2c.c +@@ -0,0 +1,356 @@ ++/* ++ * TI DaVinci (TMS320DM644x) I2C driver. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * -------------------------------------------------------- ++ * ++ * 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_DRIVER_DAVINCI_I2C ++ ++#include <i2c.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/i2c_defs.h> ++ ++#define CHECK_NACK() \ ++ do {\ ++ if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ ++ REG(I2C_CON) = 0;\ ++ return(1);\ ++ }\ ++ } while (0) ++ ++ ++static int wait_for_bus(void) ++{ ++ int stat, timeout; ++ ++ REG(I2C_STAT) = 0xffff; ++ ++ for (timeout = 0; timeout < 10; timeout++) { ++ if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) { ++ REG(I2C_STAT) = 0xffff; ++ return(0); ++ } ++ ++ REG(I2C_STAT) = stat; ++ udelay(50000); ++ } ++ ++ REG(I2C_STAT) = 0xffff; ++ return(1); ++} ++ ++ ++static int poll_i2c_irq(int mask) ++{ ++ int stat, timeout; ++ ++ for (timeout = 0; timeout < 10; timeout++) { ++ udelay(1000); ++ stat = REG(I2C_STAT); ++ if (stat & mask) { ++ return(stat); ++ } ++ } ++ ++ REG(I2C_STAT) = 0xffff; ++ return(stat | I2C_TIMEOUT); ++} ++ ++ ++void flush_rx(void) ++{ ++ int dummy; ++ ++ while (1) { ++ if (!(REG(I2C_STAT) & I2C_STAT_RRDY)) ++ break; ++ ++ dummy = REG(I2C_DRR); ++ REG(I2C_STAT) = I2C_STAT_RRDY; ++ udelay(1000); ++ } ++} ++ ++ ++void i2c_init(int speed, int slaveadd) ++{ ++ u_int32_t div, psc; ++ ++ if (REG(I2C_CON) & I2C_CON_EN) { ++ REG(I2C_CON) = 0; ++ udelay (50000); ++ } ++ ++ /* Get 1MHz into I2C internal */ ++ psc = CONFIG_SYS_HZ_CLOCK/1000000; ++ ++ div = CONFIG_SYS_HZ_CLOCK / (psc * speed); /* SCLL + SCLH */ ++ ++ REG(I2C_PSC) = psc - 1; /* 27MHz / (2 + 1) = 9MHz */ ++ REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */ ++ REG(I2C_SCLH) = div - REG(I2C_SCLL); ++ ++ REG(I2C_OA) = slaveadd; ++ REG(I2C_CNT) = 0; ++ ++ /* Interrupts must be enabled or I2C module won't work */ ++ REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | ++ I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; ++ ++ /* Now enable I2C controller (get it out of reset) */ ++ REG(I2C_CON) = I2C_CON_EN; ++ ++ udelay(1000); ++} ++ ++ ++int i2c_probe(u_int8_t chip) ++{ ++ int rc = 1; ++ ++ if (chip == REG(I2C_OA)) { ++ return(rc); ++ } ++ ++ REG(I2C_CON) = 0; ++ if (wait_for_bus()) {return(1);} ++ ++ /* try to read one byte from current (or only) address */ ++ REG(I2C_CNT) = 1; ++ REG(I2C_SA) = chip; ++ REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP | I2C_CON_FREE); ++ udelay (50000); ++ ++ if (!(REG(I2C_STAT) & I2C_STAT_NACK)) { ++ rc = 0; ++ flush_rx(); ++ REG(I2C_STAT) = 0xffff; ++ } else { ++ REG(I2C_STAT) = 0xffff; ++ REG(I2C_CON) |= I2C_CON_STP; ++ udelay(20000); ++ if (wait_for_bus()) {return(1);} ++ } ++ ++ flush_rx(); ++ REG(I2C_STAT) = 0xffff; ++ REG(I2C_CNT) = 0; ++ return(rc); ++} ++ ++ ++int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) ++{ ++ u_int32_t tmp; ++ int i; ++ ++ if ((alen < 0) || (alen > 2)) { ++ printf("%s(): bogus address length %x\n", __FUNCTION__, alen); ++ return(1); ++ } ++ ++ if (wait_for_bus()) {return(1);} ++ ++ if (alen != 0) { ++ /* Start address phase */ ++ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | ++ I2C_CON_FREE; ++ REG(I2C_CNT) = alen; ++ REG(I2C_SA) = chip; ++ REG(I2C_CON) = tmp; ++ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ switch (alen) { ++ case 2: ++ /* Send address MSByte */ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = (addr >> 8) & 0xff; ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ /* No break, fall through */ ++ case 1: ++ /* Send address LSByte */ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = addr & 0xff; ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); ++ ++ CHECK_NACK(); ++ ++ if (!(tmp & I2C_STAT_ARDY)) { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ } ++ } ++ ++ /* Address phase is over, now read 'len' bytes and stop */ ++ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP | I2C_CON_FREE; ++ REG(I2C_CNT) = len & 0xffff; ++ REG(I2C_SA) = chip; ++ REG(I2C_CON) = tmp; ++ ++ for (i = 0; i < len; i++) { ++ tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); ++ ++ CHECK_NACK(); ++ ++ if (tmp & I2C_STAT_RRDY) { ++ buf[i] = REG(I2C_DRR); ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ } ++ ++ tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (!(tmp & I2C_STAT_SCD)) { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ ++ flush_rx(); ++ REG(I2C_STAT) = 0xffff; ++ REG(I2C_CNT) = 0; ++ REG(I2C_CON) = 0; ++ ++ return(0); ++} ++ ++ ++int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) ++{ ++ u_int32_t tmp; ++ int i; ++ ++ if ((alen < 0) || (alen > 2)) { ++ printf("%s(): bogus address length %x\n", __FUNCTION__, alen); ++ return(1); ++ } ++ if (len < 0) { ++ printf("%s(): bogus length %x\n", __FUNCTION__, len); ++ return(1); ++ } ++ ++ if (wait_for_bus()) {return(1);} ++ ++ /* Start address phase */ ++ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; ++ REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; ++ REG(I2C_SA) = chip; ++ REG(I2C_CON) = tmp; ++ ++ switch (alen) { ++ case 2: ++ /* Send address MSByte */ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = (addr >> 8) & 0xff; ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ /* No break, fall through */ ++ case 1: ++ /* Send address LSByte */ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = addr & 0xff; ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ } ++ ++ for (i = 0; i < len; i++) { ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = buf[i]; ++ } else { ++ return(1); ++ } ++ } ++ ++ tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (!(tmp & I2C_STAT_SCD)) { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ ++ flush_rx(); ++ REG(I2C_STAT) = 0xffff; ++ REG(I2C_CNT) = 0; ++ REG(I2C_CON) = 0; ++ ++ return(0); ++} ++ ++#if 0 ++u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg) ++{ ++ u_int8_t tmp; ++ ++ i2c_read(chip, reg, 1, &tmp, 1); ++ return(tmp); ++} ++ ++ ++void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val) ++{ ++ u_int8_t tmp; ++ ++ i2c_write(chip, reg, 1, &tmp, 1); ++} ++#endif /* if 0 */ ++ ++#endif /* CONFIG_DRIVER_DAVINCI_I2C */ +Index: u-boot-2009.01-primus/cpu/arm926ejs/da850/lowlevel_init.S +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/cpu/arm926ejs/da850/lowlevel_init.S +@@ -0,0 +1,504 @@ ++/* ++ * Low-level board setup code for TI DA8xx SoC based boards. ++ * ++ * Copyright (C) 2008 Texas Instruments, Inc <www.ti.com> ++ * Sekhar Nori <nsekhar@ti.com> ++ * ++ * Based on TI DaVinci low level init code. Original copyrights follow. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Partially based on TI sources, original copyrights follow: ++ */ ++ ++/* ++ * Board specific setup info ++ * ++ * (C) Copyright 2003 ++ * Texas Instruments, <www.ti.com> ++ * Kshitij Gupta <Kshitij@ti.com> ++ * ++ * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004 ++ * ++ * Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004 ++ * See file CREDITS for list of people who contributed to this ++ * project. ++ * ++ * Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005 ++ * See file CREDITS for list of people who contributed to this ++ * project. ++ * ++ * Modified for DV-EVM board by Swaminathan S, Nov 2005 ++ * See file CREDITS for list of people who contributed to this ++ * project. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#include <config.h> ++#include <asm/arch/hardware.h> ++ ++.globl lowlevel_init ++lowlevel_init: ++ ++ nop ++ nop ++ nop ++ nop ++ ++ /* ++ * Call board-specific lowlevel init. ++ * That MUST be present and THAT returns ++ * back to arch calling code with "mov pc, lr." ++ */ ++ b dv_board_init ++ ++#ifndef CONFIG_USE_IRQ ++ /*-------------------------------------------------------* ++ * Mask all IRQs by clearing the global enable and setting ++ * the enable clear for all the 90 interrupts. ++ *-------------------------------------------------------*/ ++ mov r1, $0 ++ ldr r0, INTC_GLB_EN_ADDR ++ str r1, [r0] ++ ++ ldr r0, INTC_HINT_EN_ADDR ++ str r1, [r0] ++ add r0, r0, $4 ++ str r1, [r0] ++ add r0, r0, $4 ++ str r1, [r0] ++ ++ mvn r1, r1 ++ ldr r0, INTC_EN_CLR0_ADDR ++ str r1, [r0] ++ add r0, r0, $4 ++ str r1, [r0] ++ add r0, r0, $4 ++ str r1, [r0] ++#endif ++ ++ /*------------------------------------------------------* ++ * PLL0 Initialization - works only in non-secure devices ++ *------------------------------------------------------*/ ++ ++ /* TODO: Write the kick values and the PLL master lock bits */ ++ ++ /* Select OSCIN in clockmode bit in PLLCTL register. This is the only ++ * clock mode supported on DA8xx ++ */ ++ ldr r6, PLL0_PLLCTL_ADDR ++ ldr r7, PLL_CLKSRC_MASK ++ ldr r8, [r6] ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Clear the PLLENSRC bit in PLLCTL */ ++ ldr r7, PLL_ENSRC_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Bypass the PLL */ ++ ldr r7, PLL_BYPASS_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */ ++ mov r10, $0x20 ++WaitPLL0Loop: ++ subs r10, r10, $1 ++ bne WaitPLL0Loop ++ ++ /* Reset the PLL */ ++ ldr r7, PLL_RESET_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* disable PLL output */ ++ mov r7, $0x10 ++ orr r8, r8, r7 ++ str r8, [r6] ++ ++ /* Power up the PLL */ ++ ldr r7, PLL_PWRUP_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Enable the PLL from Disable Mode */ ++ ldr r7, PLL_DISABLE_ENABLE_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Wait for the PLL stabilization time - 150us assumed */ ++ mov r10, $0xE10 ++PLLStableLoop: ++ subs r10, r10, $1 ++ bne PLLStableLoop ++ ++ /* Program the PLL Multiplier */ ++ ldr r6, PLL0_PLLM_ADDR ++ mov r2, $0x18 /* 24 * 25 = 600MHz*/ ++ str r2, [r6] ++ ++ /* Program the POSTDIV Value */ ++ ldr r6, PLL0_POSTDIV_ADDR ++ mov r3, $0x01 ++ mov r3, r3, lsl $15 ++ orr r3, r3, $0x01 ++ str r3, [r6] ++ ++ /* Program the SYSCLKx dividedrs */ ++ ++ /* Following defaults are good: ++ * SYSCLK1 = /1 => 300MHz GEM ++ * SYSCLK2 = /2 => 150MHz EDMA, MMC/SD, UART1/2, SPI1 ++ * SYSCLK3 = /3 => 100MHz Possible EMIF2.5 ++ * SYSCLK4 = /4 => 75MHz INTC, PSC, EMAC, USB 1.1, I2C1 ++ * SYSCLK5 = /3 => 100MHz Possible EMIF3.0 (use DIV4p5) ++ * SYSCLK6 = /1 => 300MHz ARM ++ * SYSCLK7 = /6 => 50MHz RMII Ref Clk ++ * SYSCLK8 = /6 => 50MHz Dont use ++ * SYSCLK9 = /6 => 50MHz Dont use ++ * AUXCLK FIXED => 24Mhz Timer 0/1, 12C0, McASP AuxClk ++ */ ++ ++ /* Wait for PLL to Reset Properly - 128 OSCIN cycles*/ ++ mov r10, $128 ++ResetPPL2Loop: ++ subs r10, r10, $1 ++ bne ResetPPL2Loop ++ ++ /* Bring PLL out of Reset */ ++ ldr r6, PLL0_PLLCTL_ADDR ++ ldr r8, [r6] ++ orr r8, r8, $0x08 ++ str r8, [r6] ++ ++ /* Wait for PLL to Lock */ ++ ldr r10, PLL_LOCK_COUNT ++PLL0Lock: ++ subs r10, r10, $1 ++ bne PLL0Lock ++ ++ /* Enable the PLL */ ++ ldr r6, PLL0_PLLCTL_ADDR ++ ldr r8, [r6] ++ orr r8, r8, $0x01 ++ str r8, [r6] ++ ++ /*------------------------------------------------------* ++ * Setup the pinmux for DDR2 * ++ *------------------------------------------------------*/ ++ ++ ldr r0, PINMUX1_ADDR ++ ldr r1, PINMUX1_VAL ++ str r1, [r0] ++ ++ ldr r0, PINMUX2_ADDR ++ ldr r1, PINMUX2_VAL ++ str r1, [r0] ++ ++ ldr r0, PINMUX5_ADDR ++ ldr r1, PINMUX5_VAL ++ str r1, [r0] ++ ++ ldr r0, PINMUX6_ADDR ++ ldr r1, PINMUX6_VAL ++ str r1, [r0] ++ ++ ldr r8, PINMUX7_FLAG_CLEAR ++ ldr r7, PINMUX7_VAL ++ ldr r0, PINMUX7_ADDR ++ ldr r1, [r0] ++ and r1, r1, r8 ++ orr r1, r1, r7 ++ str r1, [r0] ++ ++ ++ /*------------------------------------------------------* ++ * Get the EMIF3 out of reset * ++ *------------------------------------------------------*/ ++ ++ /* Shut down the DDR2 LPSC Module */ ++ ldr r8, PSC_FLAG_CLEAR ++ ldr r6, MDCTL_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, r8 ++ orr r7, r7, $0x03 ++ str r7, [r6] ++ ++ /* Enable the Power Domain Transition Command */ ++ ldr r6, PSC1_PTCMD_ADDR ++ ldr r7, [r6] ++ orr r7, r7, $0x01 ++ str r7, [r6] ++ ++ /* Check for Transition Complete(PTSTAT) */ ++checkStatClkStop0: ++ ldr r6, PSC1_PTSTAT_ADDR ++ ldr r7, [r6] ++ ands r7, r7, $0x01 ++ bne checkStatClkStop0 ++ ++ /* Check for DDR2 Controller Enable Completion */ ++checkDDRStatClkStop0: ++ ldr r6, MDSTAT_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, $0x1f ++ cmp r7, $0x03 ++ bne checkDDRStatClkStop0 ++ ++ /*------------------------------------------------------* ++ * Put the EMIF3 in reset * ++ *------------------------------------------------------*/ ++ ++ /* Shut down the DDR2 LPSC Module */ ++ ldr r8, PSC_FLAG_CLEAR ++ ldr r6, MDCTL_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, r8 ++ orr r7, r7, $0x01 ++ str r7, [r6] ++ ++ /* Enable the Power Domain Transition Command */ ++ ldr r6, PSC1_PTCMD_ADDR ++ ldr r7, [r6] ++ orr r7, r7, $0x01 ++ str r7, [r6] ++ ++ /* Check for Transition Complete(PTSTAT) */ ++checkStatClkStop1: ++ ldr r6, PSC1_PTSTAT_ADDR ++ ldr r7, [r6] ++ ands r7, r7, $0x01 ++ bne checkStatClkStop1 ++ ++ /* Check for DDR2 Controller Enable Completion */ ++checkDDRStatClkStop1: ++ ldr r6, MDSTAT_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, $0x1f ++ cmp r7, $0x01 ++ bne checkDDRStatClkStop1 ++ ++ nop ++ nop ++ ++ /*------------------------------------------------------* ++ * Get the EMIF3 out of reset * ++ *------------------------------------------------------*/ ++ ++ /* Shut down the DDR2 LPSC Module */ ++ ldr r8, PSC_FLAG_CLEAR ++ ldr r6, MDCTL_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, r8 ++ orr r7, r7, $0x03 ++ str r7, [r6] ++ ++ /* Enable the Power Domain Transition Command */ ++ ldr r6, PSC1_PTCMD_ADDR ++ ldr r7, [r6] ++ orr r7, r7, $0x01 ++ str r7, [r6] ++ ++ /* Check for Transition Complete(PTSTAT) */ ++checkStatClkStop2: ++ ldr r6, PSC1_PTSTAT_ADDR ++ ldr r7, [r6] ++ ands r7, r7, $0x01 ++ bne checkStatClkStop2 ++ ++ /* Check for DDR2 Controller Enable Completion */ ++checkDDRStatClkStop2: ++ ldr r6, MDSTAT_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, $0x1f ++ cmp r7, $0x03 ++ bne checkDDRStatClkStop2 ++ ++ nop ++ nop ++ ++ /*-----------------------------------------------------* ++ * Wait before programing the SDRAM timimg values * ++ *-----------------------------------------------------*/ ++ ++ ldr r10, EMIF3_TIMING_WAIT_VAL ++emif3TimingWait: ++ sub r10, r10, $0x1 ++ cmp r10, $0x0 ++ bne emif3TimingWait ++ ++ /*------------------------------------------------------* ++ * Program EMIF3 MMRs for 133MHz SDRAM Setting * ++ *------------------------------------------------------*/ ++ ++ /* Program SDRAM Bank Config Register */ ++ ldr r6, SDCFG ++ ldr r7, SDCFG_VAL ++ str r7, [r6] ++ ++ /* Program SDRAM TIM-0 Config Register */ ++ ldr r6, SDTIM0 ++ ldr r7, SDTIM0_VAL_162MHz ++ str r7, [r6] ++ ++ /* Program SDRAM TIM-1 Config Register */ ++ ldr r6, SDTIM1 ++ ldr r7, SDTIM1_VAL_162MHz ++ str r7, [r6] ++ ++ /* Program the SDRAM Bank Config Control Register */ ++ ldr r10, MASK_VAL ++ ldr r8, SDCFG ++ ldr r9, SDCFG_VAL ++ and r9, r9, r10 ++ str r9, [r8] ++ ++ /* Program SDRAM SDREF Config Register */ ++ ldr r6, SDREF ++ ldr r7, SDREF_VAL ++ str r7, [r6] ++ ++ /* Issue a Dummy DDR2 read/write */ ++ ldr r8, DDR2_START_ADDR ++ ldr r7, DUMMY_VAL ++ str r7, [r8] ++ ldr r7, [r8] ++ ++ /* DDR Writes and Reads */ ++ ldr r6, CFGTEST ++ mov r3, $0x01 ++ str r3, [r6] ++ ++ nop ++ nop ++ nop ++ nop ++ ++ /* ++ * Call board-specific lowlevel init. ++ * That MUST be present and THAT returns ++ * back to arch calling code with "mov pc, lr." ++ */ ++ b dv_board_init ++ ++.ltorg ++ ++PINMUX1_ADDR: ++ .word PINMUX1 ++PINMUX2_ADDR: ++ .word PINMUX2 ++PINMUX5_ADDR: ++ .word PINMUX5 ++PINMUX6_ADDR: ++ .word PINMUX6 ++PINMUX7_ADDR: ++ .word PINMUX7 ++PINMUX1_VAL: ++ .word 0x11111111 ++PINMUX2_VAL: ++ .word 0x01111111 ++PINMUX5_VAL: ++ .word 0x11111110 ++PINMUX6_VAL: ++ .word 0x11111111 ++PINMUX7_FLAG_CLEAR: ++ .word 0xFFFFF000 ++PINMUX7_VAL: ++ .word 0x111 ++ ++ ++MDCTL_EMIF3: ++ .word PSC1_MDCTL + 4 * 6 ++MDSTAT_EMIF3: ++ .word PSC1_MDSTAT + 4 * 6 ++ ++PSC1_PTCMD_ADDR: ++ .word PSC1_PTCMD ++PSC1_PTSTAT_ADDR: ++ .word PSC1_PTSTAT ++ ++INTC_GLB_EN_ADDR: ++ .word INTC_GLB_EN ++INTC_EN_CLR0_ADDR: ++ .word INTC_EN_CLR0 ++INTC_HINT_EN_ADDR: ++ .word INTC_HINT_EN ++ ++PSC_FLAG_CLEAR: ++ .word 0xffffffe0 ++PSC_GEM_FLAG_CLEAR: ++ .word 0xfffffeff ++ ++/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */ ++SDREF: ++ .word DAVINCI_DDR_EMIF_CTRL_BASE + 0xc ++SDREF_VAL: ++ .word 0x000005c3 ++SDCFG: ++ .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x8 ++SDCFG_VAL: ++#ifdef SDRAM_4BANKS_10COLS ++ .word 0x00178622 ++#elif defined SDRAM_8BANKS_10COLS ++ .word 0x00178632 ++#else ++#error "Unknown SDRAM configuration!!!" ++#endif ++SDTIM0: ++ .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x10 ++SDTIM0_VAL_162MHz: ++ .word 0x28923211 ++SDTIM1: ++ .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x14 ++SDTIM1_VAL_162MHz: ++ .word 0x0016c722 ++CFGTEST: ++ .word DAVINCI_DDR_EMIF_DATA_BASE + 0x10000 ++MASK_VAL: ++ .word 0x00000fff ++EMIF3_TIMING_WAIT_VAL: ++ .word 990000 ++ ++PLL_CLKSRC_MASK: ++ .word 0xfffffeff /* Mask the Clock Mode bit */ ++PLL_ENSRC_MASK: ++ .word 0xffffffdf /* Select the PLLEN source */ ++PLL_BYPASS_MASK: ++ .word 0xfffffffe /* Put the PLL in BYPASS */ ++PLL_RESET_MASK: ++ .word 0xfffffff7 /* Put the PLL in Reset Mode */ ++PLL_PWRUP_MASK: ++ .word 0xfffffffd /* PLL Power up Mask Bit */ ++PLL_DISABLE_ENABLE_MASK: ++ .word 0xffffffef /* Enable the PLL from Disable */ ++PLL_LOCK_COUNT: ++ .word 2000 ++ ++/* PLL0 MMRs */ ++PLL0_PLLCTL_ADDR: ++ .word PLL0_PLLCTL ++PLL0_PLLM_ADDR: ++ .word PLL0_PLLM ++PLL0_POSTDIV_ADDR: ++ .word PLL0_POSTDIV ++ ++DDR2_START_ADDR: ++ .word 0xc0000000 ++DUMMY_VAL: ++ .word 0xa55aa55a +Index: u-boot-2009.01-primus/cpu/arm926ejs/da850/nand.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/cpu/arm926ejs/da850/nand.c +@@ -0,0 +1,475 @@ ++/* ++ * NAND driver for TI DaVinci based boards. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Based on Linux DaVinci NAND driver by TI. Original copyright follows: ++ */ ++ ++/* ++ * ++ * linux/drivers/mtd/nand/nand_davinci.c ++ * ++ * NAND Flash Driver ++ * ++ * Copyright (C) 2006 Texas Instruments. ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ * ++ * Overview: ++ * This is a device driver for the NAND flash device found on the ++ * DaVinci board which utilizes the Samsung k9k2g08 part. ++ * ++ Modifications: ++ ver. 1.0: Feb 2005, Vinod/Sudhakar ++ - ++ * ++ */ ++ ++#include <common.h> ++#include <asm/io.h> ++ ++#ifdef CONFIG_SYS_USE_NAND ++#if !defined(CONFIG_NAND_LEGACY) ++ ++#include <nand.h> ++#include <asm/arch/nand_defs.h> ++#include <asm/arch/emif_defs.h> ++ ++extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE]; ++ ++static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) ++{ ++ struct nand_chip *this = mtd->priv; ++ u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W; ++ ++ IO_ADDR_W &= ~(MASK_ALE|MASK_CLE); ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ if ( ctrl & NAND_CLE ) ++ IO_ADDR_W |= MASK_CLE; ++ if ( ctrl & NAND_ALE ) ++ IO_ADDR_W |= MASK_ALE; ++ this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; ++ } ++ ++ if (cmd != NAND_CMD_NONE) ++ writeb(cmd, this->IO_ADDR_W); ++} ++ ++/* Set WP on deselect, write enable on select */ ++static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) ++{ ++#define GPIO_SET_DATA01 0x01c67018 ++#define GPIO_CLR_DATA01 0x01c6701c ++#define GPIO_NAND_WP (1 << 4) ++#ifdef SONATA_BOARD_GPIOWP ++ if (chip < 0) { ++ REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP; ++ } else { ++ REG(GPIO_SET_DATA01) |= GPIO_NAND_WP; ++ } ++#endif ++} ++ ++#ifdef CONFIG_SYS_NAND_HW_ECC ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++/* Linux-compatible ECC uses MTD defaults. */ ++/* These layouts are not compatible with Linux or RBL/UBL. */ ++#ifdef CONFIG_SYS_NAND_LARGEPAGE ++static struct nand_ecclayout davinci_nand_ecclayout = { ++ .eccbytes = 12, ++ .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, ++ .oobfree = { ++ {.offset = 2, .length = 6}, ++ {.offset = 12, .length = 12}, ++ {.offset = 28, .length = 12}, ++ {.offset = 44, .length = 12}, ++ {.offset = 60, .length = 4} ++ } ++}; ++#elif defined(CONFIG_SYS_NAND_SMALLPAGE) ++static struct nand_ecclayout davinci_nand_ecclayout = { ++ .eccbytes = 3, ++ .eccpos = {0, 1, 2}, ++ .oobfree = { ++ {.offset = 6, .length = 2}, ++ {.offset = 8, .length = 8} ++ } ++}; ++#else ++#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" ++#endif ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ ++static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) ++{ ++ emifregs emif_addr; ++ int dummy; ++ ++ emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; ++ ++ dummy = emif_addr->NANDF1ECC; ++ dummy = emif_addr->NANDF2ECC; ++ dummy = emif_addr->NANDF3ECC; ++ dummy = emif_addr->NANDF4ECC; ++ ++ emif_addr->NANDFCR |= (1 << 8); ++} ++ ++static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) ++{ ++ u_int32_t ecc = 0; ++ emifregs emif_base_addr; ++ ++ emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; ++ ++ if (region == 1) ++ ecc = emif_base_addr->NANDF1ECC; ++ else if (region == 2) ++ ecc = emif_base_addr->NANDF2ECC; ++ else if (region == 3) ++ ecc = emif_base_addr->NANDF3ECC; ++ else if (region == 4) ++ ecc = emif_base_addr->NANDF4ECC; ++ ++ return(ecc); ++} ++ ++static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) ++{ ++ u_int32_t tmp; ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++ /* ++ * This is not how you should read ECCs on large page Davinci devices. ++ * The region parameter gets you ECCs for flash chips on different chip ++ * selects, not the 4x512 byte pages in a 2048 byte page. ++ * ++ * Preserved for backwards compatibility though. ++ */ ++ ++ int region, n; ++ struct nand_chip *this = mtd->priv; ++ ++ n = (this->ecc.size/512); ++ ++ region = 1; ++ while (n--) { ++ tmp = nand_davinci_readecc(mtd, region); ++ *ecc_code++ = tmp; ++ *ecc_code++ = tmp >> 16; ++ *ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0); ++ region++; ++ } ++#else ++ const int region = 1; ++ ++ tmp = nand_davinci_readecc(mtd, region); ++ ++ /* Squeeze 4 bytes ECC into 3 bytes by removing RESERVED bits ++ * and shifting. RESERVED bits are 31 to 28 and 15 to 12. */ ++ tmp = (tmp & 0x00000fff) | ((tmp & 0x0fff0000) >> 4); ++ ++ /* Invert so that erased block ECC is correct */ ++ tmp = ~tmp; ++ ++ *ecc_code++ = tmp; ++ *ecc_code++ = tmp >> 8; ++ *ecc_code++ = tmp >> 16; ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ return(0); ++} ++ ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf) ++{ ++ u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8); ++ ++ ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp)); ++ ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp)); ++ ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp)); ++} ++ ++static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data) ++{ ++ u_int32_t i; ++ u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8]; ++ u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8]; ++ u_int8_t ecc_bit[24]; ++ u_int8_t ecc_sum = 0; ++ u_int8_t find_bit = 0; ++ u_int32_t find_byte = 0; ++ int is_ecc_ff; ++ ++ is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff)); ++ ++ nand_davinci_gen_true_ecc(ecc_nand); ++ nand_davinci_gen_true_ecc(ecc_calc); ++ ++ for (i = 0; i <= 2; i++) { ++ *(ecc_nand + i) = ~(*(ecc_nand + i)); ++ *(ecc_calc + i) = ~(*(ecc_calc + i)); ++ } ++ ++ for (i = 0; i < 8; i++) { ++ tmp0_bit[i] = *ecc_nand % 2; ++ *ecc_nand = *ecc_nand / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ tmp1_bit[i] = *(ecc_nand + 1) % 2; ++ *(ecc_nand + 1) = *(ecc_nand + 1) / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ tmp2_bit[i] = *(ecc_nand + 2) % 2; ++ *(ecc_nand + 2) = *(ecc_nand + 2) / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ comp0_bit[i] = *ecc_calc % 2; ++ *ecc_calc = *ecc_calc / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ comp1_bit[i] = *(ecc_calc + 1) % 2; ++ *(ecc_calc + 1) = *(ecc_calc + 1) / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ comp2_bit[i] = *(ecc_calc + 2) % 2; ++ *(ecc_calc + 2) = *(ecc_calc + 2) / 2; ++ } ++ ++ for (i = 0; i< 6; i++) ++ ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2]; ++ ++ for (i = 0; i < 8; i++) ++ ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i]; ++ ++ for (i = 0; i < 8; i++) ++ ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i]; ++ ++ ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0]; ++ ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1]; ++ ++ for (i = 0; i < 24; i++) ++ ecc_sum += ecc_bit[i]; ++ ++ switch (ecc_sum) { ++ case 0: ++ /* Not reached because this function is not called if ++ ECC values are equal */ ++ return 0; ++ case 1: ++ /* Uncorrectable error */ ++ MTDDEBUG (MTD_DEBUG_LEVEL0, ++ "ECC UNCORRECTED_ERROR 1\n"); ++ return(-1); ++ case 12: ++ /* Correctable error */ ++ find_byte = (ecc_bit[23] << 8) + ++ (ecc_bit[21] << 7) + ++ (ecc_bit[19] << 6) + ++ (ecc_bit[17] << 5) + ++ (ecc_bit[15] << 4) + ++ (ecc_bit[13] << 3) + ++ (ecc_bit[11] << 2) + ++ (ecc_bit[9] << 1) + ++ ecc_bit[7]; ++ ++ find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; ++ ++ MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC " ++ "error at offset: %d, bit: %d\n", ++ find_byte, find_bit); ++ ++ page_data[find_byte] ^= (1 << find_bit); ++ ++ return(0); ++ default: ++ if (is_ecc_ff) { ++ if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0) ++ return(0); ++ } ++ MTDDEBUG (MTD_DEBUG_LEVEL0, ++ "UNCORRECTED_ERROR default\n"); ++ return(-1); ++ } ++} ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ ++static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) ++{ ++ struct nand_chip *this = mtd->priv; ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++ int block_count = 0, i, rc; ++ ++ block_count = (this->ecc.size/512); ++ for (i = 0; i < block_count; i++) { ++ if (memcmp(read_ecc, calc_ecc, 3) != 0) { ++ rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat); ++ if (rc < 0) { ++ return(rc); ++ } ++ } ++ read_ecc += 3; ++ calc_ecc += 3; ++ dat += 512; ++ } ++#else ++ u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) | ++ (read_ecc[2] << 16); ++ u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) | ++ (calc_ecc[2] << 16); ++ u_int32_t diff = ecc_calc ^ ecc_nand; ++ ++ if (diff) { ++ if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) { ++ /* Correctable error */ ++ if ((diff >> (12 + 3)) < this->ecc.size) { ++ uint8_t find_bit = 1 << ((diff >> 12) & 7); ++ uint32_t find_byte = diff >> (12 + 3); ++ ++ dat[find_byte] ^= find_bit; ++ MTDDEBUG(MTD_DEBUG_LEVEL0, "Correcting single " ++ "bit ECC error at offset: %d, bit: " ++ "%d\n", find_byte, find_bit); ++ return 1; ++ } else { ++ return -1; ++ } ++ } else if (!(diff & (diff - 1))) { ++ /* Single bit ECC error in the ECC itself, ++ nothing to fix */ ++ MTDDEBUG(MTD_DEBUG_LEVEL0, "Single bit ECC error in " ++ "ECC.\n"); ++ return 1; ++ } else { ++ /* Uncorrectable error */ ++ MTDDEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n"); ++ return -1; ++ } ++ } ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ return(0); ++} ++#endif /* CONFIG_SYS_NAND_HW_ECC */ ++ ++static int nand_davinci_dev_ready(struct mtd_info *mtd) ++{ ++ emifregs emif_addr; ++ ++ emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; ++ ++ return(emif_addr->NANDFSR & 0x1); ++} ++ ++static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this) ++{ ++ while(!nand_davinci_dev_ready(mtd)) {;} ++ *NAND_CE0CLE = NAND_STATUS; ++ return(*NAND_CE0DATA); ++} ++ ++static void nand_flash_init(void) ++{ ++ u_int32_t acfg1 = 0x3ffffffc; ++ u_int32_t acfg2 = 0x3ffffffc; ++ u_int32_t acfg3 = 0x3ffffffc; ++ u_int32_t acfg4 = 0x3ffffffc; ++ emifregs emif_regs; ++ ++ /*------------------------------------------------------------------* ++ * NAND FLASH CHIP TIMEOUT @ 459 MHz * ++ * * ++ * AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz * ++ * AEMIF.CLK period = 1/76.5 MHz = 13.1 ns * ++ * * ++ *------------------------------------------------------------------*/ ++ acfg1 = 0 ++ | (0 << 31 ) /* selectStrobe */ ++ | (0 << 30 ) /* extWait */ ++ | (1 << 26 ) /* writeSetup 10 ns */ ++ | (3 << 20 ) /* writeStrobe 40 ns */ ++ | (1 << 17 ) /* writeHold 10 ns */ ++ | (1 << 13 ) /* readSetup 10 ns */ ++ | (5 << 7 ) /* readStrobe 60 ns */ ++ | (1 << 4 ) /* readHold 10 ns */ ++ | (3 << 2 ) /* turnAround ?? ns */ ++ | (0 << 0 ) /* asyncSize 8-bit bus */ ++ ; ++ ++ emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; ++ ++ emif_regs->AWCCR |= 0x10000000; ++ emif_regs->AB1CR = acfg1; /* 0x08244128 */; ++ emif_regs->AB2CR = acfg2; ++ emif_regs->AB3CR = acfg3; ++ emif_regs->AB4CR = acfg4; ++ emif_regs->NANDFCR = 0x00000101; ++} ++ ++int board_nand_init(struct nand_chip *nand) ++{ ++ nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA; ++ nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA; ++ nand->chip_delay = 0; ++ nand->select_chip = nand_davinci_select_chip; ++#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT ++ nand->options = NAND_USE_FLASH_BBT; ++#endif ++#ifdef CONFIG_SYS_NAND_HW_ECC ++ nand->ecc.mode = NAND_ECC_HW; ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++ nand->ecc.layout = &davinci_nand_ecclayout; ++#ifdef CONFIG_SYS_NAND_LARGEPAGE ++ nand->ecc.size = 2048; ++ nand->ecc.bytes = 12; ++#elif defined(CONFIG_SYS_NAND_SMALLPAGE) ++ nand->ecc.size = 512; ++ nand->ecc.bytes = 3; ++#else ++#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" ++#endif ++#else ++ nand->ecc.size = 512; ++ nand->ecc.bytes = 3; ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ nand->ecc.calculate = nand_davinci_calculate_ecc; ++ nand->ecc.correct = nand_davinci_correct_data; ++ nand->ecc.hwctl = nand_davinci_enable_hwecc; ++#else ++ nand->ecc.mode = NAND_ECC_SOFT; ++#endif /* CONFIG_SYS_NAND_HW_ECC */ ++ ++ /* Set address of hardware control function */ ++ nand->cmd_ctrl = nand_davinci_hwcontrol; ++ ++ nand->dev_ready = nand_davinci_dev_ready; ++ nand->waitfunc = nand_davinci_waitfunc; ++ ++ nand_flash_init(); ++ ++ return(0); ++} ++ ++#else ++#error "U-Boot legacy NAND support not available for DaVinci chips" ++#endif ++#endif /* CONFIG_SYS_USE_NAND */ +Index: u-boot-2009.01-primus/cpu/arm926ejs/da850/reset.S +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/cpu/arm926ejs/da850/reset.S +@@ -0,0 +1,77 @@ ++/* ++ * Processor reset using WDT for TI TMS320DM644x SoC. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * ----------------------------------------------------- ++ * ++ * 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 ++ */ ++ ++.globl reset_cpu ++reset_cpu: ++ ldr r0, WDT_TGCR ++ mov r1, $0x08 ++ str r1, [r0] ++ ldr r1, [r0] ++ orr r1, r1, $0x03 ++ str r1, [r0] ++ mov r1, $0 ++ ldr r0, WDT_TIM12 ++ str r1, [r0] ++ ldr r0, WDT_TIM34 ++ str r1, [r0] ++ ldr r0, WDT_PRD12 ++ str r1, [r0] ++ ldr r0, WDT_PRD34 ++ str r1, [r0] ++ ldr r0, WDT_TCR ++ ldr r1, [r0] ++ orr r1, r1, $0x40 ++ str r1, [r0] ++ ldr r0, WDT_WDTCR ++ ldr r1, [r0] ++ orr r1, r1, $0x4000 ++ str r1, [r0] ++ ldr r1, WDTCR_VAL1 ++ str r1, [r0] ++ ldr r1, WDTCR_VAL2 ++ str r1, [r0] ++ nop ++ nop ++ nop ++ nop ++reset_cpu_loop: ++ b reset_cpu_loop ++ ++WDT_TGCR: ++ .word 0x01c21c24 ++WDT_TIM12: ++ .word 0x01c21c10 ++WDT_TIM34: ++ .word 0x01c21c14 ++WDT_PRD12: ++ .word 0x01c21c18 ++WDT_PRD34: ++ .word 0x01c21c1c ++WDT_TCR: ++ .word 0x01c21c20 ++WDT_WDTCR: ++ .word 0x01c21c28 ++WDTCR_VAL1: ++ .word 0xa5c64000 ++WDTCR_VAL2: ++ .word 0xda7e4000 +Index: u-boot-2009.01-primus/cpu/arm926ejs/da850/timer.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/cpu/arm926ejs/da850/timer.c +@@ -0,0 +1,148 @@ ++/* ++ * (C) Copyright 2003 ++ * Texas Instruments <www.ti.com> ++ * ++ * (C) Copyright 2002 ++ * Sysgo Real-Time Solutions, GmbH <www.elinos.com> ++ * Marius Groeger <mgroeger@sysgo.de> ++ * ++ * (C) Copyright 2002 ++ * Sysgo Real-Time Solutions, GmbH <www.elinos.com> ++ * Alex Zuepke <azu@sysgo.de> ++ * ++ * (C) Copyright 2002-2004 ++ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> ++ * ++ * (C) Copyright 2004 ++ * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * 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 <arm926ejs.h> ++ ++typedef volatile struct { ++ u_int32_t pid12; ++ u_int32_t emumgt; ++ u_int32_t na1; ++ u_int32_t na2; ++ u_int32_t tim12; ++ u_int32_t tim34; ++ u_int32_t prd12; ++ u_int32_t prd34; ++ u_int32_t tcr; ++ u_int32_t tgcr; ++ u_int32_t wdtcr; ++} davinci_timer; ++ ++davinci_timer *timer = (davinci_timer *)CONFIG_SYS_TIMERBASE; ++ ++#define TIMER_LOAD_VAL (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ) ++#define TIM_CLK_DIV 16 ++ ++static ulong timestamp; ++static ulong lastinc; ++ ++int timer_init(void) ++{ ++ /* We are using timer34 in unchained 32-bit mode, full speed */ ++ timer->tcr = 0x0; ++ timer->tgcr = 0x0; ++ timer->tgcr = 0x06 | ((TIM_CLK_DIV - 1) << 8); ++ timer->tim34 = 0x0; ++ timer->prd34 = TIMER_LOAD_VAL; ++ lastinc = 0; ++ timestamp = 0; ++ timer->tcr = 2 << 22; ++ ++ return(0); ++} ++ ++void reset_timer(void) ++{ ++ timer->tcr = 0x0; ++ timer->tim34 = 0; ++ lastinc = 0; ++ timestamp = 0; ++ timer->tcr = 2 << 22; ++} ++ ++static ulong get_timer_raw(void) ++{ ++ ulong now = timer->tim34; ++ ++ if (now >= lastinc) { ++ /* normal mode */ ++ timestamp += now - lastinc; ++ } else { ++ /* overflow ... */ ++ timestamp += now + TIMER_LOAD_VAL - lastinc; ++ } ++ lastinc = now; ++ return timestamp; ++} ++ ++ulong get_timer(ulong base) ++{ ++ return((get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base); ++} ++ ++void set_timer(ulong t) ++{ ++ timestamp = t; ++} ++ ++void udelay(unsigned long usec) ++{ ++ ulong tmo; ++ ulong endtime; ++ signed long diff; ++ ++ tmo = CONFIG_SYS_HZ_CLOCK / 1000; ++ tmo *= usec; ++ tmo /= (1000 * TIM_CLK_DIV); ++ ++ endtime = get_timer_raw() + tmo; ++ ++ do { ++ ulong now = get_timer_raw(); ++ diff = endtime - now; ++ } while (diff >= 0); ++} ++ ++/* ++ * This function is derived from PowerPC code (read timebase as long long). ++ * On ARM it just returns the timer value. ++ */ ++unsigned long long get_ticks(void) ++{ ++ return(get_timer(0)); ++} ++ ++/* ++ * This function is derived from PowerPC code (timebase clock frequency). ++ * On ARM it returns the number of timer ticks per second. ++ */ ++ulong get_tbclk(void) ++{ ++ return CONFIG_SYS_HZ; ++} +Index: u-boot-2009.01-primus/include/asm-arm/arch-da850/emac_defs.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/include/asm-arm/arch-da850/emac_defs.h +@@ -0,0 +1,331 @@ ++/* ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Based on: ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * dm644x_emac.h ++ * ++ * TI DaVinci (DM644X) EMAC peripheral driver header for DV-EVM ++ * ++ * Copyright (C) 2005 Texas Instruments. ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ ++ * Modifications: ++ * ver. 1.0: Sep 2005, TI PSP Team - Created EMAC version for uBoot. ++ * ++ */ ++ ++#ifndef _DM644X_EMAC_H_ ++#define _DM644X_EMAC_H_ ++ ++#include <asm/arch/hardware.h> ++ ++#define EMAC_BASE_ADDR DAVINCI_EMAC_CNTRL_REGS_BASE ++#define EMAC_WRAPPER_BASE_ADDR DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE ++#define EMAC_WRAPPER_RAM_ADDR DAVINCI_EMAC_WRAPPER_RAM_BASE ++#define EMAC_MDIO_BASE_ADDR DAVINCI_MDIO_CNTRL_REGS_BASE ++ ++/* MDIO module input frequency */ ++#define EMAC_MDIO_BUS_FREQ clk_get(DAVINCI_MDIO_CLKID) ++ ++/* MDIO clock output frequency */ ++#define EMAC_MDIO_CLOCK_FREQ 2000000 /* 2.0 MHz */ ++ ++/* Ethernet Min/Max packet size */ ++#define EMAC_MIN_ETHERNET_PKT_SIZE 60 ++#define EMAC_MAX_ETHERNET_PKT_SIZE 1518 ++#define EMAC_PKT_ALIGN 18 /* 1518 + 18 = 1536 (packet aligned on 32 byte boundry) */ ++ ++/* Number of RX packet buffers ++ * NOTE: Only 1 buffer supported as of now ++ */ ++#define EMAC_MAX_RX_BUFFERS 10 ++ ++ ++/*********************************************** ++ ******** Internally used macros *************** ++ ***********************************************/ ++ ++#define EMAC_CH_TX 1 ++#define EMAC_CH_RX 0 ++ ++/* Each descriptor occupies 4 words, lets start RX desc's at 0 and ++ * reserve space for 64 descriptors max ++ */ ++#define EMAC_RX_DESC_BASE 0x0 ++#define EMAC_TX_DESC_BASE 0x1000 ++ ++/* EMAC Teardown value */ ++#define EMAC_TEARDOWN_VALUE 0xfffffffc ++ ++/* MII Status Register */ ++#define MII_STATUS_REG 1 ++ ++/* Number of statistics registers */ ++#define EMAC_NUM_STATS 36 ++ ++ ++/* EMAC Descriptor */ ++typedef volatile struct _emac_desc ++{ ++ u_int32_t next; /* Pointer to next descriptor in chain */ ++ u_int8_t *buffer; /* Pointer to data buffer */ ++ u_int32_t buff_off_len; /* Buffer Offset(MSW) and Length(LSW) */ ++ u_int32_t pkt_flag_len; /* Packet Flags(MSW) and Length(LSW) */ ++} emac_desc; ++ ++/* CPPI bit positions */ ++#define EMAC_CPPI_SOP_BIT (0x80000000) ++#define EMAC_CPPI_EOP_BIT (0x40000000) ++#define EMAC_CPPI_OWNERSHIP_BIT (0x20000000) ++#define EMAC_CPPI_EOQ_BIT (0x10000000) ++#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT (0x08000000) ++#define EMAC_CPPI_PASS_CRC_BIT (0x04000000) ++ ++#define EMAC_CPPI_RX_ERROR_FRAME (0x03fc0000) ++ ++#define EMAC_MACCONTROL_RMIISPEED_100 (1 << 15) ++#define EMAC_MACCONTROL_MIIEN_ENABLE (0x20) ++#define EMAC_MACCONTROL_FULLDUPLEX_ENABLE (0x1) ++ ++#define EMAC_RXMBPENABLE_RXCAFEN_ENABLE (0x200000) ++#define EMAC_RXMBPENABLE_RXBROADEN (0x2000) ++ ++ ++#define MDIO_CONTROL_IDLE (0x80000000) ++#define MDIO_CONTROL_ENABLE (0x40000000) ++#define MDIO_CONTROL_FAULT_ENABLE (0x40000) ++#define MDIO_CONTROL_FAULT (0x80000) ++#define MDIO_USERACCESS0_GO (0x80000000) ++#define MDIO_USERACCESS0_WRITE_READ (0x0) ++#define MDIO_USERACCESS0_WRITE_WRITE (0x40000000) ++#define MDIO_USERACCESS0_ACK (0x20000000) ++ ++/* Ethernet MAC Registers Structure */ ++typedef struct { ++ dv_reg TXIDVER; ++ dv_reg TXCONTROL; ++ dv_reg TXTEARDOWN; ++ u_int8_t RSVD0[4]; ++ dv_reg RXIDVER; ++ dv_reg RXCONTROL; ++ dv_reg RXTEARDOWN; ++ u_int8_t RSVD1[100]; ++ dv_reg TXINTSTATRAW; ++ dv_reg TXINTSTATMASKED; ++ dv_reg TXINTMASKSET; ++ dv_reg TXINTMASKCLEAR; ++ dv_reg MACINVECTOR; ++ u_int8_t RSVD2[12]; ++ dv_reg RXINTSTATRAW; ++ dv_reg RXINTSTATMASKED; ++ dv_reg RXINTMASKSET; ++ dv_reg RXINTMASKCLEAR; ++ dv_reg MACINTSTATRAW; ++ dv_reg MACINTSTATMASKED; ++ dv_reg MACINTMASKSET; ++ dv_reg MACINTMASKCLEAR; ++ u_int8_t RSVD3[64]; ++ dv_reg RXMBPENABLE; ++ dv_reg RXUNICASTSET; ++ dv_reg RXUNICASTCLEAR; ++ dv_reg RXMAXLEN; ++ dv_reg RXBUFFEROFFSET; ++ dv_reg RXFILTERLOWTHRESH; ++ u_int8_t RSVD4[8]; ++ dv_reg RX0FLOWTHRESH; ++ dv_reg RX1FLOWTHRESH; ++ dv_reg RX2FLOWTHRESH; ++ dv_reg RX3FLOWTHRESH; ++ dv_reg RX4FLOWTHRESH; ++ dv_reg RX5FLOWTHRESH; ++ dv_reg RX6FLOWTHRESH; ++ dv_reg RX7FLOWTHRESH; ++ dv_reg RX0FREEBUFFER; ++ dv_reg RX1FREEBUFFER; ++ dv_reg RX2FREEBUFFER; ++ dv_reg RX3FREEBUFFER; ++ dv_reg RX4FREEBUFFER; ++ dv_reg RX5FREEBUFFER; ++ dv_reg RX6FREEBUFFER; ++ dv_reg RX7FREEBUFFER; ++ dv_reg MACCONTROL; ++ dv_reg MACSTATUS; ++ dv_reg EMCONTROL; ++ dv_reg FIFOCONTROL; ++ dv_reg MACCONFIG; ++ dv_reg SOFTRESET; ++ u_int8_t RSVD5[88]; ++ dv_reg MACSRCADDRLO; ++ dv_reg MACSRCADDRHI; ++ dv_reg MACHASH1; ++ dv_reg MACHASH2; ++ dv_reg BOFFTEST; ++ dv_reg TPACETEST; ++ dv_reg RXPAUSE; ++ dv_reg TXPAUSE; ++ u_int8_t RSVD6[16]; ++ dv_reg RXGOODFRAMES; ++ dv_reg RXBCASTFRAMES; ++ dv_reg RXMCASTFRAMES; ++ dv_reg RXPAUSEFRAMES; ++ dv_reg RXCRCERRORS; ++ dv_reg RXALIGNCODEERRORS; ++ dv_reg RXOVERSIZED; ++ dv_reg RXJABBER; ++ dv_reg RXUNDERSIZED; ++ dv_reg RXFRAGMENTS; ++ dv_reg RXFILTERED; ++ dv_reg RXQOSFILTERED; ++ dv_reg RXOCTETS; ++ dv_reg TXGOODFRAMES; ++ dv_reg TXBCASTFRAMES; ++ dv_reg TXMCASTFRAMES; ++ dv_reg TXPAUSEFRAMES; ++ dv_reg TXDEFERRED; ++ dv_reg TXCOLLISION; ++ dv_reg TXSINGLECOLL; ++ dv_reg TXMULTICOLL; ++ dv_reg TXEXCESSIVECOLL; ++ dv_reg TXLATECOLL; ++ dv_reg TXUNDERRUN; ++ dv_reg TXCARRIERSENSE; ++ dv_reg TXOCTETS; ++ dv_reg FRAME64; ++ dv_reg FRAME65T127; ++ dv_reg FRAME128T255; ++ dv_reg FRAME256T511; ++ dv_reg FRAME512T1023; ++ dv_reg FRAME1024TUP; ++ dv_reg NETOCTETS; ++ dv_reg RXSOFOVERRUNS; ++ dv_reg RXMOFOVERRUNS; ++ dv_reg RXDMAOVERRUNS; ++ u_int8_t RSVD7[624]; ++ dv_reg MACADDRLO; ++ dv_reg MACADDRHI; ++ dv_reg MACINDEX; ++ u_int8_t RSVD8[244]; ++ dv_reg TX0HDP; ++ dv_reg TX1HDP; ++ dv_reg TX2HDP; ++ dv_reg TX3HDP; ++ dv_reg TX4HDP; ++ dv_reg TX5HDP; ++ dv_reg TX6HDP; ++ dv_reg TX7HDP; ++ dv_reg RX0HDP; ++ dv_reg RX1HDP; ++ dv_reg RX2HDP; ++ dv_reg RX3HDP; ++ dv_reg RX4HDP; ++ dv_reg RX5HDP; ++ dv_reg RX6HDP; ++ dv_reg RX7HDP; ++ dv_reg TX0CP; ++ dv_reg TX1CP; ++ dv_reg TX2CP; ++ dv_reg TX3CP; ++ dv_reg TX4CP; ++ dv_reg TX5CP; ++ dv_reg TX6CP; ++ dv_reg TX7CP; ++ dv_reg RX0CP; ++ dv_reg RX1CP; ++ dv_reg RX2CP; ++ dv_reg RX3CP; ++ dv_reg RX4CP; ++ dv_reg RX5CP; ++ dv_reg RX6CP; ++ dv_reg RX7CP; ++} emac_regs; ++ ++/* EMAC Wrapper Registers Structure */ ++typedef struct { ++ dv_reg REV; ++ dv_reg SOFTRESET; ++ dv_reg INTCONTROL; ++ dv_reg C0RXTHRESHEN; ++ dv_reg C0RXEN; ++ dv_reg C0TXEN; ++ dv_reg C0MISCEN; ++ dv_reg C1RXTHRESHEN; ++ dv_reg C1RXEN; ++ dv_reg C1TXEN; ++ dv_reg C1MISCEN; ++ dv_reg C2RXTHRESHEN; ++ dv_reg C2RXEN; ++ dv_reg C2TXEN; ++ dv_reg C2MISCEN; ++ dv_reg C0RXTHRESHSTAT; ++ dv_reg C0RXSTAT; ++ dv_reg C0TXSTAT; ++ dv_reg C0MISCSTAT; ++ dv_reg C1RXTHRESHSTAT; ++ dv_reg C1RXSTAT; ++ dv_reg C1TXSTAT; ++ dv_reg C1MISCSTAT; ++ dv_reg C2RXTHRESHSTAT; ++ dv_reg C2RXSTAT; ++ dv_reg C2TXSTAT; ++ dv_reg C2MISCSTAT; ++ dv_reg C0RXIMAX; ++ dv_reg C0TXIMAX; ++ dv_reg C1RXIMAX; ++ dv_reg C1TXIMAX; ++ dv_reg C2RXIMAX; ++ dv_reg C2TXIMAX; ++} ewrap_regs; ++ ++ ++/* EMAC MDIO Registers Structure */ ++typedef struct { ++ dv_reg VERSION; ++ dv_reg CONTROL; ++ dv_reg ALIVE; ++ dv_reg LINK; ++ dv_reg LINKINTRAW; ++ dv_reg LINKINTMASKED; ++ u_int8_t RSVD0[8]; ++ dv_reg USERINTRAW; ++ dv_reg USERINTMASKED; ++ dv_reg USERINTMASKSET; ++ dv_reg USERINTMASKCLEAR; ++ u_int8_t RSVD1[80]; ++ dv_reg USERACCESS0; ++ dv_reg USERPHYSEL0; ++ dv_reg USERACCESS1; ++ dv_reg USERPHYSEL1; ++} mdio_regs; ++ ++int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data); ++int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data); ++ ++typedef struct ++{ ++ char name[64]; ++ int (*init)(int phy_addr); ++ int (*is_phy_connected)(int phy_addr); ++ int (*get_link_speed)(int phy_addr); ++ int (*auto_negotiate)(int phy_addr); ++} phy_t; ++ ++#endif /* _DM644X_EMAC_H_ */ +Index: u-boot-2009.01-primus/include/asm-arm/arch-da850/emif_defs.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/include/asm-arm/arch-da850/emif_defs.h +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * 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 ++ */ ++#ifndef _EMIF_DEFS_H_ ++#define _EMIF_DEFS_H_ ++ ++#include <asm/arch/hardware.h> ++ ++typedef struct { ++ dv_reg ERCSR; ++ dv_reg AWCCR; ++ dv_reg SDBCR; ++ dv_reg SDRCR; ++ dv_reg AB1CR; ++ dv_reg AB2CR; ++ dv_reg AB3CR; ++ dv_reg AB4CR; ++ dv_reg SDTIMR; ++ dv_reg DDRSR; ++ dv_reg DDRPHYCR; ++ dv_reg DDRPHYSR; ++ dv_reg TOTAR; ++ dv_reg TOTACTR; ++ dv_reg DDRPHYID_REV; ++ dv_reg SDSRETR; ++ dv_reg EIRR; ++ dv_reg EIMR; ++ dv_reg EIMSR; ++ dv_reg EIMCR; ++ dv_reg IOCTRLR; ++ dv_reg IOSTATR; ++ u_int8_t RSVD0[8]; ++ dv_reg NANDFCR; ++ dv_reg NANDFSR; ++ u_int8_t RSVD1[8]; ++ dv_reg NANDF1ECC; ++ dv_reg NANDF2ECC; ++ dv_reg NANDF3ECC; ++ dv_reg NANDF4ECC; ++} emif_registers; ++ ++typedef emif_registers *emifregs; ++#endif +Index: u-boot-2009.01-primus/include/asm-arm/arch-da850/hardware.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/include/asm-arm/arch-da850/hardware.h +@@ -0,0 +1,199 @@ ++/* ++ * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc ++ * ++ * Based on hardware.h for DaVinci. Original Copyrights follow. ++ * ++ * Sergey Kubushyn <ksi@koi8.net> ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Based on: ++ * ++ * ------------------------------------------------------------------------- ++ * ++ * linux/include/asm-arm/arch-davinci/hardware.h ++ * ++ * Copyright (C) 2006 Texas Instruments. ++ * ++ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * 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., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++#ifndef __ASM_ARCH_HARDWARE_H ++#define __ASM_ARCH_HARDWARE_H ++ ++#include <config.h> ++ ++#ifndef __ASSEMBLY__ ++ ++#include <asm/sizes.h> ++ ++#define REG(addr) (*(volatile unsigned int *)(addr)) ++#define REG_P(addr) ((volatile unsigned int *)(addr)) ++ ++typedef volatile unsigned int dv_reg; ++typedef volatile unsigned int * dv_reg_p; ++ ++#endif ++ ++/* ++ * Base register addresses ++ */ ++#define DAVINCI_UART0_BASE (0x01c42000) ++#define DAVINCI_UART1_BASE (0x01d0c000) ++#define DAVINCI_UART2_BASE (0x01d0d000) ++#define DAVINCI_I2C0_BASE (0x01c22000) ++#define DAVINCI_I2C1_BASE (0x01e28000) ++#define DAVINCI_TIMER0_BASE (0x01c20000) ++#define DAVINCI_TIMER1_BASE (0x01c21000) ++#define DAVINCI_WDOG_BASE (0x01c21000) ++#define DAVINCI_PLL_CNTRL0_BASE (0x01c11000) ++#define DAVINCI_PSC0_BASE (0x01c10000) ++#define DAVINCI_PSC1_BASE (0x01e27000) ++#define DAVINCI_SPI0_BASE (0x01c41000) ++#define DAVINCI_SPI1_BASE (0x01e12000) ++#define DAVINCI_GPIO_BASE (0x01e26000) ++#define DAVINCI_EMAC_CNTRL_REGS_BASE (0x01e23000) ++#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE (0x01e22000) ++#define DAVINCI_EMAC_WRAPPER_RAM_BASE (0x01e20000) ++#define DAVINCI_MDIO_CNTRL_REGS_BASE (0x01e24000) ++#define DAVINCI_ASYNC_EMIF_CNTRL_BASE (0x68000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE (0x40000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE (0x60000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE (0x62000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE4_BASE (0x64000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE5_BASE (0x66000000) ++#define DAVINCI_DDR_EMIF_CTRL_BASE (0xb0000000) ++#define DAVINCI_DDR_EMIF_DATA_BASE (0xc0000000) ++#define DAVINCI_INTC_BASE (0xfffee000) ++#define DAVINCI_BOOTCFG_BASE (0x01c14000) ++ ++/* Clock IDs */ ++#define DAVINCI_PLLM_CLKID (0xFF + 0) ++#define DAVINCI_PLLC_CLKID (0xFF + 1) ++#define DAVINCI_AUXCLK_CLKID (0xFF + 2) ++#define DAVINCI_MDIO_CLKID 4 ++#define DAVINCI_SPI0_CLKID 2 ++#define DAVINCI_UART0_CLKID 2 ++#define DAVINCI_ARM_CLKID 6 ++ ++/* Power and Sleep Controller (PSC) Domains */ ++#define DAVINCI_GPSC_ARMDOMAIN 0 ++#define DAVINCI_GPSC_DSPDOMAIN 1 ++ ++/* LPSCs in PSC0 */ ++#define DAVINCI_LPSC_TPCC 0 ++#define DAVINCI_LPSC_TPTC0 1 ++#define DAVINCI_LPSC_TPTC1 2 ++#define DAVINCI_LPSC_AEMIF 3 ++#define DAVINCI_LPSC_SPI0 4 ++#define DAVINCI_LPSC_MMC_SD 5 ++#define DAVINCI_LPSC_AINTC 6 ++#define DAVINCI_LPSC_ARM_RAM_ROM 7 ++#define DAVINCI_LPSC_SECCTL_KEYMGR 8 ++#define DAVINCI_LPSC_UART0 9 ++#define DAVINCI_LPSC_SCR0 10 ++#define DAVINCI_LPSC_SCR1 11 ++#define DAVINCI_LPSC_SCR2 12 ++#define DAVINCI_LPSC_DMAX 13 ++#define DAVINCI_LPSC_ARM 14 ++#define DAVINCI_LPSC_GEM 15 ++ ++/* for LPSCs in PSC1, 32 + actual id is being used for differentiation */ ++#define DAVINCI_LPSC_USB11 (32 + 1) ++#define DAVINCI_LPSC_USB20 (32 + 2) ++#define DAVINCI_LPSC_GPIO (32 + 3) ++#define DAVINCI_LPSC_UHPI (32 + 4) ++#define DAVINCI_LPSC_EMAC (32 + 5) ++#define DAVINCI_LPSC_DDR_EMIF (32 + 6) ++#define DAVINCI_LPSC_McASP0 (32 + 7) ++#define DAVINCI_LPSC_McASP1 (32 + 8) ++#define DAVINCI_LPSC_McASP2 (32 + 9) ++#define DAVINCI_LPSC_SPI1 (32 + 10) ++#define DAVINCI_LPSC_I2C1 (32 + 11) ++#define DAVINCI_LPSC_UART1 (32 + 12) ++#define DAVINCI_LPSC_UART2 (32 + 13) ++#define DAVINCI_LPSC_LCDC (32 + 16) ++#define DAVINCI_LPSC_ePWM (32 + 17) ++#define DAVINCI_LPSC_eCAP (32 + 20) ++#define DAVINCI_LPSC_eQEP (32 + 21) ++#define DAVINCI_LPSC_SCR_P0 (32 + 22) ++#define DAVINCI_LPSC_SCR_P1 (32 + 23) ++#define DAVINCI_LPSC_CR_P3 (32 + 26) ++#define DAVINCI_LPSC_L3_CBA_RAM (32 + 31) ++ ++/* Some PSC defines */ ++ ++#define PSC0_MDCTL (DAVINCI_PSC0_BASE + 0xa00) ++#define PSC0_MDSTAT (DAVINCI_PSC0_BASE + 0x800) ++#define PSC0_PTCMD (DAVINCI_PSC0_BASE + 0x120) ++#define PSC0_PTSTAT (DAVINCI_PSC0_BASE + 0x128) ++ ++#define PSC1_MDCTL (DAVINCI_PSC1_BASE + 0xa00) ++#define PSC1_MDSTAT (DAVINCI_PSC1_BASE + 0x800) ++#define PSC1_PTCMD (DAVINCI_PSC1_BASE + 0x120) ++#define PSC1_PTSTAT (DAVINCI_PSC1_BASE + 0x128) ++ ++/* Some PLL defines */ ++#define PLL0_PLLCTL (DAVINCI_PLL_CNTRL0_BASE + 0x100) ++#define PLL0_PLLM (DAVINCI_PLL_CNTRL0_BASE + 0x110) ++#define PLL0_PREDIV (DAVINCI_PLL_CNTRL0_BASE + 0x114) ++#define PLL0_POSTDIV (DAVINCI_PLL_CNTRL0_BASE + 0x128) ++#define PLL0_DIV1 (DAVINCI_PLL_CNTRL0_BASE + 0x118) ++#define PLL0_DIV2 (DAVINCI_PLL_CNTRL0_BASE + 0x11c) ++#define PLL0_DIV3 (DAVINCI_PLL_CNTRL0_BASE + 0x120) ++#define PLL0_DIV4 (DAVINCI_PLL_CNTRL0_BASE + 0x160) ++#define PLL0_DIV5 (DAVINCI_PLL_CNTRL0_BASE + 0x164) ++#define PLL0_DIV6 (DAVINCI_PLL_CNTRL0_BASE + 0x168) ++#define PLL0_DIV7 (DAVINCI_PLL_CNTRL0_BASE + 0x16c) ++#define PLL0_DIV8 (DAVINCI_PLL_CNTRL0_BASE + 0x170) ++#define PLL0_DIV9 (DAVINCI_PLL_CNTRL0_BASE + 0x114) ++ ++/* Boot config */ ++#define KICK0 (DAVINCI_BOOTCFG_BASE + 0x38) ++#define KICK1 (DAVINCI_BOOTCFG_BASE + 0x3c) ++#define PINMUX0 (DAVINCI_BOOTCFG_BASE + 0x120) ++#define PINMUX1 (DAVINCI_BOOTCFG_BASE + 0x124) ++#define PINMUX2 (DAVINCI_BOOTCFG_BASE + 0x128) ++#define PINMUX3 (DAVINCI_BOOTCFG_BASE + 0x12c) ++#define PINMUX4 (DAVINCI_BOOTCFG_BASE + 0x130) ++#define PINMUX5 (DAVINCI_BOOTCFG_BASE + 0x134) ++#define PINMUX6 (DAVINCI_BOOTCFG_BASE + 0x138) ++#define PINMUX7 (DAVINCI_BOOTCFG_BASE + 0x13c) ++#define PINMUX8 (DAVINCI_BOOTCFG_BASE + 0x140) ++#define PINMUX9 (DAVINCI_BOOTCFG_BASE + 0x144) ++#define PINMUX10 (DAVINCI_BOOTCFG_BASE + 0x148) ++#define PINMUX11 (DAVINCI_BOOTCFG_BASE + 0x14c) ++#define PINMUX12 (DAVINCI_BOOTCFG_BASE + 0x150) ++#define PINMUX13 (DAVINCI_BOOTCFG_BASE + 0x154) ++#define PINMUX14 (DAVINCI_BOOTCFG_BASE + 0x158) ++#define PINMUX15 (DAVINCI_BOOTCFG_BASE + 0x15C) ++#define PINMUX16 (DAVINCI_BOOTCFG_BASE + 0x160) ++#define PINMUX17 (DAVINCI_BOOTCFG_BASE + 0x164) ++#define PINMUX18 (DAVINCI_BOOTCFG_BASE + 0x168) ++#define PINMUX19 (DAVINCI_BOOTCFG_BASE + 0x16c) ++#define SUSPSRC (DAVINCI_BOOTCFG_BASE + 0x170) ++#define CFGCHIP0 (DAVINCI_BOOTCFG_BASE + 0x17c) ++ ++/* Interrupt controller */ ++#define INTC_GLB_EN (DAVINCI_INTC_BASE + 0x10) ++#define INTC_HINT_EN (DAVINCI_INTC_BASE + 0x1500) ++#define INTC_EN_CLR0 (DAVINCI_INTC_BASE + 0x380) ++ ++#endif /* __ASM_ARCH_HARDWARE_H */ +Index: u-boot-2009.01-primus/include/asm-arm/arch-da850/i2c_defs.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/include/asm-arm/arch-da850/i2c_defs.h +@@ -0,0 +1,95 @@ ++/* ++ * (C) Copyright 2004 ++ * Texas Instruments, <www.ti.com> ++ * ++ * Some changes copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * 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 ++ */ ++#ifndef _DAVINCI_I2C_H_ ++#define _DAVINCI_I2C_H_ ++ ++#define I2C_WRITE 0 ++#define I2C_READ 1 ++ ++#define I2C_BASE 0x01c22000 ++ ++#define I2C_OA (I2C_BASE + 0x00) ++#define I2C_IE (I2C_BASE + 0x04) ++#define I2C_STAT (I2C_BASE + 0x08) ++#define I2C_SCLL (I2C_BASE + 0x0c) ++#define I2C_SCLH (I2C_BASE + 0x10) ++#define I2C_CNT (I2C_BASE + 0x14) ++#define I2C_DRR (I2C_BASE + 0x18) ++#define I2C_SA (I2C_BASE + 0x1c) ++#define I2C_DXR (I2C_BASE + 0x20) ++#define I2C_CON (I2C_BASE + 0x24) ++#define I2C_IV (I2C_BASE + 0x28) ++#define I2C_PSC (I2C_BASE + 0x30) ++ ++/* I2C masks */ ++ ++/* I2C Interrupt Enable Register (I2C_IE): */ ++#define I2C_IE_SCD_IE (1 << 5) /* Stop condition detect interrupt enable */ ++#define I2C_IE_XRDY_IE (1 << 4) /* Transmit data ready interrupt enable */ ++#define I2C_IE_RRDY_IE (1 << 3) /* Receive data ready interrupt enable */ ++#define I2C_IE_ARDY_IE (1 << 2) /* Register access ready interrupt enable */ ++#define I2C_IE_NACK_IE (1 << 1) /* No acknowledgment interrupt enable */ ++#define I2C_IE_AL_IE (1 << 0) /* Arbitration lost interrupt enable */ ++ ++/* I2C Status Register (I2C_STAT): */ ++ ++#define I2C_STAT_BB (1 << 12) /* Bus busy */ ++#define I2C_STAT_ROVR (1 << 11) /* Receive overrun */ ++#define I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ ++#define I2C_STAT_AAS (1 << 9) /* Address as slave */ ++#define I2C_STAT_SCD (1 << 5) /* Stop condition detect */ ++#define I2C_STAT_XRDY (1 << 4) /* Transmit data ready */ ++#define I2C_STAT_RRDY (1 << 3) /* Receive data ready */ ++#define I2C_STAT_ARDY (1 << 2) /* Register access ready */ ++#define I2C_STAT_NACK (1 << 1) /* No acknowledgment interrupt enable */ ++#define I2C_STAT_AL (1 << 0) /* Arbitration lost interrupt enable */ ++ ++ ++/* I2C Interrupt Code Register (I2C_INTCODE): */ ++ ++#define I2C_INTCODE_MASK 7 ++#define I2C_INTCODE_NONE 0 ++#define I2C_INTCODE_AL 1 /* Arbitration lost */ ++#define I2C_INTCODE_NAK 2 /* No acknowledgement/general call */ ++#define I2C_INTCODE_ARDY 3 /* Register access ready */ ++#define I2C_INTCODE_RRDY 4 /* Rcv data ready */ ++#define I2C_INTCODE_XRDY 5 /* Xmit data ready */ ++#define I2C_INTCODE_SCD 6 /* Stop condition detect */ ++ ++ ++/* I2C Configuration Register (I2C_CON): */ ++ ++#define I2C_CON_EN (1 << 5) /* I2C module enable */ ++#define I2C_CON_STB (1 << 4) /* Start byte mode (master mode only) */ ++#define I2C_CON_MST (1 << 10) /* Master/slave mode */ ++#define I2C_CON_TRX (1 << 9) /* Transmitter/receiver mode (master mode only) */ ++#define I2C_CON_XA (1 << 8) /* Expand address */ ++#define I2C_CON_STP (1 << 11) /* Stop condition (master mode only) */ ++#define I2C_CON_STT (1 << 13) /* Start condition (master mode only) */ ++#define I2C_CON_FREE (1 << 14) /* Free run on emulation */ ++ ++#define I2C_TIMEOUT 0xffff0000 /* Timeout mask for poll_i2c_irq() */ ++ ++#endif +Index: u-boot-2009.01-primus/include/asm-arm/arch-da850/nand_defs.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01-primus/include/asm-arm/arch-da850/nand_defs.h +@@ -0,0 +1,164 @@ ++/* ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Parts shamelesly stolen from Linux Kernel source tree. ++ * ++ * ------------------------------------------------------------ ++ * ++ * 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 ++ */ ++#ifndef _NAND_DEFS_H_ ++#define _NAND_DEFS_H_ ++ ++#include <asm/arch/hardware.h> ++ ++#define MASK_CLE 0x10 ++//#define MASK_ALE 0x0a ++#define MASK_ALE 0x08 ++ ++ ++#define NAND_CE0CLE ((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x10)) ++//#define NAND_CE0ALE ((volatile u_int8_t *)(CFG_NAND_BASE + 0x0a)) ++#define NAND_CE0ALE ((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x08)) ++#define NAND_CE0DATA ((volatile u_int8_t *)CONFIG_SYS_NAND_BASE) ++ ++typedef struct { ++ u_int32_t NRCSR; ++ u_int32_t AWCCR; ++ u_int8_t RSVD0[8]; ++ u_int32_t AB1CR; ++ u_int32_t AB2CR; ++ u_int32_t AB3CR; ++ u_int32_t AB4CR; ++ u_int8_t RSVD1[32]; ++ u_int32_t NIRR; ++ u_int32_t NIMR; ++ u_int32_t NIMSR; ++ u_int32_t NIMCR; ++ u_int8_t RSVD2[16]; ++ u_int32_t NANDFCR; ++ u_int32_t NANDFSR; ++ u_int8_t RSVD3[8]; ++ u_int32_t NANDF1ECC; ++ u_int32_t NANDF2ECC; ++ u_int32_t NANDF3ECC; ++ u_int32_t NANDF4ECC; ++ u_int8_t RSVD4[4]; ++ u_int32_t IODFTECR; ++ u_int32_t IODFTGCR; ++ u_int8_t RSVD5[4]; ++ u_int32_t IODFTMRLR; ++ u_int32_t IODFTMRMR; ++ u_int32_t IODFTMRMSBR; ++ u_int8_t RSVD6[20]; ++ u_int32_t MODRNR; ++ u_int8_t RSVD7[76]; ++ u_int32_t CE0DATA; ++ u_int32_t CE0ALE; ++ u_int32_t CE0CLE; ++ u_int8_t RSVD8[4]; ++ u_int32_t CE1DATA; ++ u_int32_t CE1ALE; ++ u_int32_t CE1CLE; ++ u_int8_t RSVD9[4]; ++ u_int32_t CE2DATA; ++ u_int32_t CE2ALE; ++ u_int32_t CE2CLE; ++ u_int8_t RSVD10[4]; ++ u_int32_t CE3DATA; ++ u_int32_t CE3ALE; ++ u_int32_t CE3CLE; ++} nand_registers; ++ ++typedef volatile nand_registers *nandregs; ++ ++#define NAND_READ_START 0x00 ++#define NAND_READ_END 0x30 ++#define NAND_STATUS 0x70 ++ ++#ifdef CFG_NAND_HW_ECC ++#define NAND_Ecc_P1e (1 << 0) ++#define NAND_Ecc_P2e (1 << 1) ++#define NAND_Ecc_P4e (1 << 2) ++#define NAND_Ecc_P8e (1 << 3) ++#define NAND_Ecc_P16e (1 << 4) ++#define NAND_Ecc_P32e (1 << 5) ++#define NAND_Ecc_P64e (1 << 6) ++#define NAND_Ecc_P128e (1 << 7) ++#define NAND_Ecc_P256e (1 << 8) ++#define NAND_Ecc_P512e (1 << 9) ++#define NAND_Ecc_P1024e (1 << 10) ++#define NAND_Ecc_P2048e (1 << 11) ++ ++#define NAND_Ecc_P1o (1 << 16) ++#define NAND_Ecc_P2o (1 << 17) ++#define NAND_Ecc_P4o (1 << 18) ++#define NAND_Ecc_P8o (1 << 19) ++#define NAND_Ecc_P16o (1 << 20) ++#define NAND_Ecc_P32o (1 << 21) ++#define NAND_Ecc_P64o (1 << 22) ++#define NAND_Ecc_P128o (1 << 23) ++#define NAND_Ecc_P256o (1 << 24) ++#define NAND_Ecc_P512o (1 << 25) ++#define NAND_Ecc_P1024o (1 << 26) ++#define NAND_Ecc_P2048o (1 << 27) ++ ++#define TF(v) (v ? 1 : 0) ++ ++#define P2048e(a) (TF(a & NAND_Ecc_P2048e) << 0) ++#define P2048o(a) (TF(a & NAND_Ecc_P2048o) << 1) ++#define P1e(a) (TF(a & NAND_Ecc_P1e) << 2) ++#define P1o(a) (TF(a & NAND_Ecc_P1o) << 3) ++#define P2e(a) (TF(a & NAND_Ecc_P2e) << 4) ++#define P2o(a) (TF(a & NAND_Ecc_P2o) << 5) ++#define P4e(a) (TF(a & NAND_Ecc_P4e) << 6) ++#define P4o(a) (TF(a & NAND_Ecc_P4o) << 7) ++ ++#define P8e(a) (TF(a & NAND_Ecc_P8e) << 0) ++#define P8o(a) (TF(a & NAND_Ecc_P8o) << 1) ++#define P16e(a) (TF(a & NAND_Ecc_P16e) << 2) ++#define P16o(a) (TF(a & NAND_Ecc_P16o) << 3) ++#define P32e(a) (TF(a & NAND_Ecc_P32e) << 4) ++#define P32o(a) (TF(a & NAND_Ecc_P32o) << 5) ++#define P64e(a) (TF(a & NAND_Ecc_P64e) << 6) ++#define P64o(a) (TF(a & NAND_Ecc_P64o) << 7) ++ ++#define P128e(a) (TF(a & NAND_Ecc_P128e) << 0) ++#define P128o(a) (TF(a & NAND_Ecc_P128o) << 1) ++#define P256e(a) (TF(a & NAND_Ecc_P256e) << 2) ++#define P256o(a) (TF(a & NAND_Ecc_P256o) << 3) ++#define P512e(a) (TF(a & NAND_Ecc_P512e) << 4) ++#define P512o(a) (TF(a & NAND_Ecc_P512o) << 5) ++#define P1024e(a) (TF(a & NAND_Ecc_P1024e) << 6) ++#define P1024o(a) (TF(a & NAND_Ecc_P1024o) << 7) ++ ++#define P8e_s(a) (TF(a & NAND_Ecc_P8e) << 0) ++#define P8o_s(a) (TF(a & NAND_Ecc_P8o) << 1) ++#define P16e_s(a) (TF(a & NAND_Ecc_P16e) << 2) ++#define P16o_s(a) (TF(a & NAND_Ecc_P16o) << 3) ++#define P1e_s(a) (TF(a & NAND_Ecc_P1e) << 4) ++#define P1o_s(a) (TF(a & NAND_Ecc_P1o) << 5) ++#define P2e_s(a) (TF(a & NAND_Ecc_P2e) << 6) ++#define P2o_s(a) (TF(a & NAND_Ecc_P2o) << 7) ++ ++#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) ++#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) ++#endif ++ ++#endif +Index: u-boot-2009.01-primus/Makefile +=================================================================== +--- u-boot-2009.01-primus.orig/Makefile ++++ u-boot-2009.01-primus/Makefile +@@ -2719,6 +2719,9 @@ davinci_sonata_config : unconfig + da8xx_evm_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs da8xx-evm da8xx da8xx + ++da850_evm_config : unconfig ++ @$(MKCONFIG) $(@:_config=) arm arm926ejs da850-evm da850 da850 ++ + lpd7a400_config \ + lpd7a404_config: unconfig + @$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x diff --git a/patches/primus_port.patch b/patches/primus_port.patch new file mode 100644 index 0000000000..5698e0dd7f --- /dev/null +++ b/patches/primus_port.patch @@ -0,0 +1,5062 @@ +Index: u-boot-2009.01/include/configs/da8xx_evm.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01/include/configs/da8xx_evm.h +@@ -0,0 +1,223 @@ ++/* ++ * Copyright (C) 2008 Texas Instruments, Inc <www.ti.com> ++ * ++ * Based on davinci_dvevm.h. Original Copyrights follow: ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * 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 ++ */ ++ ++#ifndef __CONFIG_H ++#define __CONFIG_H ++#include <asm/sizes.h> ++#include <asm/arch/hardware.h> ++ ++/*=======*/ ++/* Board */ ++/*=======*/ ++//#define CFG_USE_SPIFLASH ++#define CONFIG_SYS_USE_NAND ++ ++/*===================*/ ++/* SoC Configuration */ ++/*===================*/ ++#define CONFIG_ARM926EJS /* arm926ejs CPU core */ ++#define CONFIG_DA8XX /* TI DA8xx SoC */ ++#define CONFIG_SYS_CLK_FREQ clk_get(DAVINCI_ARM_CLKID) /* Arm Clock */ ++#define CFG_OSCIN_FREQ 24000000 ++#define CONFIG_SYS_TIMERBASE DAVINCI_TIMER0_BASE /* use timer 0 */ ++#define CONFIG_SYS_HZ_CLOCK clk_get(DAVINCI_AUXCLK_CLKID) /* Timer Input clock freq */ ++#define CONFIG_SYS_HZ 1000 ++#undef CONFIG_SKIP_LOWLEVEL_INIT /* U-Boot is _always_ loaded by a bootloader */ ++#define CONFIG_SKIP_RELOCATE_UBOOT /* to a proper address, init done */ ++ ++/*=============*/ ++/* Memory Info */ ++/*=============*/ ++#define CONFIG_SYS_MALLOC_LEN (0x10000 + 128*1024) /* malloc() len */ ++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* reserved for initial data */ ++#define PHYS_SDRAM_1 DAVINCI_DDR_EMIF_DATA_BASE /* DDR Start */ ++#define PHYS_SDRAM_1_SIZE 0x04000000 /* SDRAM size 64MB */ ++#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 /* memtest start address */ ++#define CONFIG_SYS_MEMTEST_END (PHYS_SDRAM_1 + 16*1024*1024) /* 16MB RAM test */ ++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ ++#define CONFIG_STACKSIZE (256*1024) /* regular stack */ ++#define SDRAM_4BANKS_10COLS /* TODO: Update this! */ ++ ++/*====================*/ ++/* Serial Driver info */ ++/*====================*/ ++#define CONFIG_SYS_NS16550 ++#define CONFIG_SYS_NS16550_SERIAL ++#define CONFIG_SYS_NS16550_REG_SIZE 4 /* NS16550 register size */ ++#define CONFIG_SYS_NS16550_COM1 DAVINCI_UART2_BASE /* Base address of UART2 */ ++#define CONFIG_SYS_NS16550_CLK clk_get(DAVINCI_UART2_CLKID) /* Input clock to NS16550 */ ++#define CONFIG_CONS_INDEX 1 /* use UART0 for console */ ++#define CONFIG_BAUDRATE 115200 /* Default baud rate */ ++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } ++ ++/*===================*/ ++/* I2C Configuration */ ++/*===================*/ ++#define CONFIG_HARD_I2C ++#define CONFIG_DRIVER_DAVINCI_I2C ++#define CONFIG_SYS_I2C_SPEED 25000 /* 100Kbps won't work, silicon bug */ ++#define CONFIG_SYS_I2C_SLAVE 10 /* Bogus, master-only in U-Boot */ ++ ++/*====================================================*/ ++/* I2C EEPROM definitions for catalyst 24W256 EEPROM chip */ ++/*====================================================*/ ++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 ++#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 ++#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 6 ++#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 20 ++ ++/*==================================*/ ++/* Network & Ethernet Configuration */ ++/*==================================*/ ++#define CONFIG_DRIVER_TI_EMAC ++#define CONFIG_MII ++#define CONFIG_BOOTP_DEFAULT ++#define CONFIG_BOOTP_DNS ++#define CONFIG_BOOTP_DNS2 ++#define CONFIG_BOOTP_SEND_HOSTNAME ++#define CONFIG_NET_RETRY_COUNT 10 ++ ++/*=====================*/ ++/* Flash & Environment */ ++/*=====================*/ ++#ifdef CONFIG_SYS_USE_NAND ++#undef CONFIG_ENV_IS_IN_FLASH ++#define CONFIG_SYS_NO_FLASH ++#define CONFIG_ENV_IS_IN_NAND /* U-Boot env in NAND Flash */ ++#define CONFIG_ENV_SIZE SZ_128K ++#define CONFIG_NAND_1BIT_ECC ++#define CONFIG_NAND_CS 3 ++#define CONFIG_SYS_NAND_BASE DAVINCI_ASYNC_EMIF_DATA_CE3_BASE ++#define CONFIG_CLE_MASK 0x10 ++#define CONFIG_ALE_MASK 0x8 ++#define CONFIG_NAND_HW_ECC ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ ++#define NAND_MAX_CHIPS 1 ++#define CONFIG_ENV_OFFSET 0x0 /* Block 0--not used by bootcode */ ++#define DEF_BOOTM "" ++#endif ++ ++#ifdef CONFIG_SYS_USE_NOR ++#define CONFIG_ENV_IS_IN_FLASH ++#undef CONFIG_SYS_NO_FLASH ++#define CFG_FLASH_CFI_DRIVER ++#define CFG_FLASH_CFI ++#define CFG_MAX_FLASH_BANKS 1 /* max number of flash banks */ ++#define CFG_FLASH_SECT_SZ 0x10000 /* 64KB sect size AMD Flash */ ++#define CONFIG_ENV_OFFSET (CFG_FLASH_SECT_SZ*3) ++#define CFG_FLASH_BASE DAVINCI_ASYNC_EMIF_DATA_CE2_BASE ++#define PHYS_FLASH_SIZE 0x2000000 /* Flash size 32MB */ ++#define CFG_MAX_FLASH_SECT (PHYS_FLASH_SIZE/CFG_FLASH_SECT_SZ) ++#define CONFIG_ENV_SECT_SIZE CFG_FLASH_SECT_SZ /* Env sector Size */ ++#endif ++ ++#ifdef CFG_USE_SPIFLASH ++#undef CONFIG_ENV_IS_IN_FLASH ++#undef CONFIG_ENV_IS_IN_NAND ++#define CONFIG_ENV_IS_IN_SPI_FLASH ++#define CONFIG_ENV_SIZE SZ_16K ++#define CONFIG_ENV_OFFSET SZ_256K ++#define CONFIG_ENV_SECT_SIZE SZ_4K ++#define CONFIG_SYS_NO_FLASH ++#define CONFIG_SPI ++#define CONFIG_SPI_FLASH ++#define CONFIG_SPI_FLASH_WINBOND ++#define CONFIG_DAVINCI_SPI ++#define CFG_SPI_BASE DAVINCI_SPI0_BASE ++#define CFG_SPI_CLK clk_get(DAVINCI_SPI0_CLKID) ++#define CONFIG_SF_DEFAULT_SPEED 50000000 ++#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED ++#endif ++ ++ ++/*==============================*/ ++/* U-Boot general configuration */ ++/*==============================*/ ++#undef CONFIG_USE_IRQ /* No IRQ/FIQ in U-Boot */ ++#define CONFIG_MISC_INIT_R ++#undef CONFIG_BOOTDELAY ++#define CONFIG_BOOTFILE "uImage" /* Boot file name */ ++#define CONFIG_SYS_PROMPT "U-Boot > " /* Monitor Command Prompt */ ++#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print buffer sz */ ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ ++#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_MEMTEST_START + 0x700000) /* default Linux kernel load address */ ++#define CONFIG_VERSION_VARIABLE ++#define CONFIG_AUTO_COMPLETE /* Won't work with hush so far, may be later */ ++#define CONFIG_SYS_HUSH_PARSER ++#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " ++#define CONFIG_CMDLINE_EDITING ++#define CONFIG_SYS_LONGHELP ++#define CONFIG_CRC32_VERIFY ++#define CONFIG_MX_CYCLIC ++ ++/*===================*/ ++/* Linux Information */ ++/*===================*/ ++#define LINUX_BOOT_PARAM_ADDR (CONFIG_SYS_MEMTEST_START + 0x100) ++#define CONFIG_CMDLINE_TAG ++#define CONFIG_SETUP_MEMORY_TAGS ++#define CONFIG_BOOTARGS "mem=32M console=ttyS2,115200n8 root=/dev/mtdblock/2 rw noinitrd ip=dhcp" ++#define CONFIG_BOOTCOMMAND "" ++#define CONFIG_BOOTDELAY 3 ++ ++/*=================*/ ++/* U-Boot commands */ ++/*=================*/ ++#include <config_cmd_default.h> ++#define CONFIG_CMD_ENV ++#define CONFIG_CMD_ASKENV ++#define CONFIG_CMD_DHCP ++#define CONFIG_CMD_DIAG ++#define CONFIG_CMD_MII ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_SAVES ++#define CONFIG_CMD_MEMORY ++#undef CONFIG_CMD_BDI ++#undef CONFIG_CMD_FPGA ++#undef CONFIG_CMD_SETGETDCR ++#define CONFIG_CMD_EEPROM ++ ++#ifdef CONFIG_SYS_USE_NAND ++#undef CONFIG_CMD_FLASH ++#undef CONFIG_CMD_IMLS ++#define CONFIG_CMD_NAND ++#endif ++ ++#ifdef CFG_USE_SPIFLASH ++#undef CONFIG_CMD_IMLS ++#undef CONFIG_CMD_FLASH ++#define CONFIG_CMD_SF ++#endif ++ ++#if !defined(CONFIG_SYS_USE_NAND) && !defined(CONFIG_SYS_USE_NOR) && !defined(CFG_USE_SPIFLASH) ++#define CFG_ENV_IS_NOWHERE ++#define CONFIG_SYS_NO_FLASH ++#define CONFIG_ENV_SIZE SZ_16K ++#undef CONFIG_CMD_IMLS ++#undef CONFIG_CMD_FLASH ++#undef CONFIG_CMD_ENV ++#endif ++ ++#endif /* __CONFIG_H */ +Index: u-boot-2009.01/board/da8xx/da8xx-evm/Makefile +=================================================================== +--- /dev/null ++++ u-boot-2009.01/board/da8xx/da8xx-evm/Makefile +@@ -0,0 +1,52 @@ ++# ++# (C) Copyright 2000, 2001, 2002 ++# Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++# ++# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++# ++# 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).a ++ ++COBJS := dv_board.o ++SOBJS := board_init.o ++ ++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(COBJS)) ++SOBJS := $(addprefix $(obj),$(SOBJS)) ++ ++$(LIB): $(obj).depend $(OBJS) $(SOBJS) ++ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) ++ ++clean: ++ rm -f $(SOBJS) $(OBJS) ++ ++distclean: clean ++ rm -f $(LIB) core *.bak *~ .depend ++ ++######################################################################### ++# This is for $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +Index: u-boot-2009.01/board/da8xx/da8xx-evm/board_init.S +=================================================================== +--- /dev/null ++++ u-boot-2009.01/board/da8xx/da8xx-evm/board_init.S +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Board-specific low level initialization code. Called at the very end ++ * of cpu/arm926ejs/davinci/lowlevel_init.S. Just returns if there is no ++ * initialization required. ++ * ++ * 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> ++ ++.globl dv_board_init ++dv_board_init: ++ ++ mov pc, lr +Index: u-boot-2009.01/board/da8xx/da8xx-evm/config.mk +=================================================================== +--- /dev/null ++++ u-boot-2009.01/board/da8xx/da8xx-evm/config.mk +@@ -0,0 +1,30 @@ ++# ++# (C) Copyright 2002 ++# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> ++# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> ++# ++# (C) Copyright 2003 ++# Texas Instruments, <www.ti.com> ++# Swaminathan <swami.iyer@ti.com> ++# ++# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++# ++# (C) Copyright 2008 ++# Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> ++# ++# Texas Instruments DA8xx EVM board (ARM925EJS) cpu ++# see http://www.ti.com/ for more information on Texas Instruments ++# ++# DA8xx EVM has 1 bank of 64 MB SDRAM (2 16Meg x16 chips). ++# Physical Address: ++# C000'0000 to C400'0000 ++# ++# Linux-Kernel is expected to be at C000'8000, entry C000'8000 ++# (mem base + reserved) ++# ++# we load ourself to C108 '0000 ++# ++# ++ ++#Provide at least 16MB spacing between us and the Linux Kernel image ++TEXT_BASE = 0xC1080000 +Index: u-boot-2009.01/board/da8xx/da8xx-evm/dv_board.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/board/da8xx/da8xx-evm/dv_board.c +@@ -0,0 +1,231 @@ ++/* ++ * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> ++ * ++ * Modified for DA8xx EVM. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Parts are shamelessly stolen from various TI sources, original copyright ++ * follows: ++ * ----------------------------------------------------------------- ++ * ++ * Copyright (C) 2004 Texas Instruments. ++ * ++ * ---------------------------------------------------------------------------- ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ */ ++ ++#include <common.h> ++#include <i2c.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/emac_defs.h> ++ ++#define MACH_TYPE_DA8XX_EVM 1781 ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++extern void timer_init(void); ++extern int eth_hw_init(void); ++ ++/* Works on Always On power domain only (no PD argument) */ ++void lpsc_on(unsigned int id) ++{ ++ dv_reg_p mdstat, mdctl, ptstat, ptcmd; ++ ++ if (id >= 64) ++ return; ++ ++ if(id < 32) { ++ mdstat = REG_P(PSC0_MDSTAT + (id * 4)); ++ mdctl = REG_P(PSC0_MDCTL + (id * 4)); ++ ptstat = REG_P(PSC0_PTSTAT); ++ ptcmd = REG_P(PSC0_PTCMD); ++ } else { ++ id -= 32; ++ mdstat = REG_P(PSC1_MDSTAT + (id * 4)); ++ mdctl = REG_P(PSC1_MDCTL + (id * 4)); ++ ptstat = REG_P(PSC1_PTSTAT); ++ ptcmd = REG_P(PSC1_PTCMD); ++ } ++ ++ while (*ptstat & 0x01) {;} ++ ++ if ((*mdstat & 0x1f) == 0x03) ++ return; /* Already on and enabled */ ++ ++ *mdctl |= 0x03; ++ ++ /* Special treatment for some modules as for sprue14 p.7.4.2 */ ++ /* TBD: Confirm if such cases exist for Primus */ ++ if (0) ++ *mdctl |= 0x200; ++ ++ *ptcmd = 0x01; ++ ++ while (*ptstat & 0x01) {;} ++ while ((*mdstat & 0x1f) != 0x03) {;} /* Probably an overkill... */ ++} ++ ++int board_init(void) ++{ ++ ++ dv_reg_p intc; ++ ++ /*-------------------------------------------------------* ++ * Mask all IRQs by clearing the global enable and setting ++ * the enable clear for all the 90 interrupts. This code is ++ * also included in low level init. Including it here in case ++ * low level init is skipped. Not removing it from low level ++ * init in case some of the low level init code generates ++ * interrupts... Not expected... but you never know... ++ *-------------------------------------------------------*/ ++ ++#ifndef CONFIG_USE_IRQ ++ intc = REG_P(INTC_GLB_EN); ++ intc[0] = 0; ++ ++ intc = REG_P(INTC_HINT_EN); ++ intc[0] = 0; ++ intc[1] = 0; ++ intc[2] = 0; ++ ++ intc = REG_P(INTC_EN_CLR0); ++ intc[0] = 0xFFFFFFFF; ++ intc[1] = 0xFFFFFFFF; ++ intc[2] = 0xFFFFFFFF; ++#endif ++ ++ /* arch number of the board */ ++ gd->bd->bi_arch_number = MACH_TYPE_DA8XX_EVM; ++ ++ /* address of boot parameters */ ++ gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; ++ ++ /* setup the SUSPSRC for ARM to control emulation suspend */ ++ REG(SUSPSRC) &= ~( (1 << 27) /* Timer0 */ ++ | (1 << 21) /* SPI0 */ ++ | (1 << 20) /* UART2 */ ++ | (1 << 5) /* EMAC */ ++ | (1 << 16) /* I2C0 */ ++ ); ++ ++ /* Power on required peripherals ++ * ARM does not have acess by default to PSC0 and PSC1 ++ * assuming here that the DSP bootloader has set the IOPU ++ * such that PSC access is available to ARM ++ */ ++ lpsc_on(DAVINCI_LPSC_AEMIF); /* NAND, NOR */ ++ lpsc_on(DAVINCI_LPSC_SPI0); /* Serial Flash */ ++ lpsc_on(DAVINCI_LPSC_EMAC); /* image download */ ++ lpsc_on(DAVINCI_LPSC_UART2); /* console */ ++ lpsc_on(DAVINCI_LPSC_GPIO); ++ ++ /* Pin Muxing support */ ++ ++ /* write the kick registers to unlock the PINMUX registers */ ++ REG(KICK0) = 0x83e70b13; /* Kick0 unlock */ ++ REG(KICK1) = 0x95a4f1e0; /* Kick1 unlock */ ++ ++#ifdef CONFIG_SPI_FLASH ++ /* SPI0 */ ++ REG(PINMUX7) &= 0x00000FFF; ++ REG(PINMUX7) |= 0x11111000; ++#endif ++ ++#ifdef CONFIG_DRIVER_TI_EMAC ++ /* RMII clock is sourced externally */ ++ REG(PINMUX9) &= 0xFF0FFFFF; ++ REG(PINMUX10) &= 0x0000000F; ++ REG(PINMUX10) |= 0x22222220; ++ REG(PINMUX11) &= 0xFFFFFF00; ++ REG(PINMUX11) |= 0x00000022; ++#endif ++ ++ /* Async EMIF */ ++#if defined(CFG_USE_NAND) || defined(CFG_USE_NOR) ++ REG(PINMUX13) &= 0x00FFFFFF; ++ REG(PINMUX13) |= 0x11000000; ++ REG(PINMUX14) = 0x11111111; ++ REG(PINMUX15) = 0x11111111; ++ REG(PINMUX16) = 0x11111111; ++ REG(PINMUX17) = 0x11111111; ++ REG(PINMUX18) = 0x11111111; ++ REG(PINMUX19) &= 0xFFFFFFF0; ++ REG(PINMUX19) |= 0x1; ++#endif ++ ++ /* UART Muxing and enabling */ ++ REG(PINMUX8) &= 0x0FFFFFFF; ++ REG(PINMUX8) |= 0x20000000; ++ ++ REG(PINMUX9) &= 0xFFFFFFF0; ++ REG(PINMUX9) |= 0x00000002; ++ ++ REG(DAVINCI_UART2_BASE + 0x30) = 0xE001; ++ ++ /* I2C muxing */ ++ REG(PINMUX8) &= 0xFFF00FFF; ++ REG(PINMUX8) |= 0x00022000; ++ ++ /* write the kick registers to lock the PINMUX registers */ ++ REG(KICK0) = 0x0; /* Kick0 lock */ ++ REG(KICK1) = 0x0; /* Kick1 lock */ ++ ++ return(0); ++} ++ ++int misc_init_r (void) ++{ ++ u_int8_t tmp[20], buf[10]; ++ int i; ++ ++ printf ("ARM Clock : %d Hz\n", clk_get(DAVINCI_ARM_CLKID)); ++ ++ /* Set Ethernet MAC address from EEPROM */ ++ if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0x7f00, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, 6)) { ++ printf("\nEEPROM @ 0x%02x read FAILED!!!\n", CONFIG_SYS_I2C_EEPROM_ADDR); ++ } else { ++ tmp[0] = 0xff; ++ for (i = 0; i < 6; i++) ++ tmp[0] &= buf[i]; ++ ++ if ((tmp[0] != 0xff) && (getenv("ethaddr") == NULL)) { ++ sprintf((char *)&tmp[0], "%02x:%02x:%02x:%02x:%02x:%02x", ++ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); ++ setenv("ethaddr", (char *)&tmp[0]); ++ } ++ } ++ ++ tmp[0] = 0x01; ++ tmp[1] = 0x23; ++ if(i2c_write(0x5f, 0, 0, tmp, 2)) { ++ printf("Ethernet switch start failed!\n"); ++ } ++ ++ if (!eth_hw_init()) { ++ printf("Error: Ethernet init failed!\n"); ++ } ++ ++ return(0); ++} ++ ++int dram_init(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++ ++ return(0); ++} +Index: u-boot-2009.01/board/da8xx/da8xx-evm/u-boot.lds +=================================================================== +--- /dev/null ++++ u-boot-2009.01/board/da8xx/da8xx-evm/u-boot.lds +@@ -0,0 +1,52 @@ ++/* ++ * (C) Copyright 2002 ++ * Gary Jennejohn, DENX Software Engineering, <gj@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 ++ */ ++ ++OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") ++OUTPUT_ARCH(arm) ++ENTRY(_start) ++SECTIONS ++{ ++ . = 0x00000000; ++ . = ALIGN(4); ++ .text : ++ { ++ cpu/arm926ejs/start.o (.text) ++ *(.text) ++ } ++ . = ALIGN(4); ++ .rodata : { *(.rodata) } ++ . = ALIGN(4); ++ .data : { *(.data) } ++ . = ALIGN(4); ++ .got : { *(.got) } ++ ++ . = .; ++ __u_boot_cmd_start = .; ++ .u_boot_cmd : { *(.u_boot_cmd) } ++ __u_boot_cmd_end = .; ++ ++ . = ALIGN(4); ++ __bss_start = .; ++ .bss (NOLOAD) : { *(.bss) } ++ _end = .; ++} +Index: u-boot-2009.01/cpu/arm926ejs/da8xx/Makefile +=================================================================== +--- /dev/null ++++ u-boot-2009.01/cpu/arm926ejs/da8xx/Makefile +@@ -0,0 +1,49 @@ ++# ++# (C) Copyright 2000-2006 ++# Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++# ++# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++# ++# See file CREDITS for list of people who contributed to this ++# project. ++# ++# This program is free software; you can redistribute it and/or ++# modify it under the terms of the GNU General Public License as ++# published by the Free Software Foundation; either version 2 of ++# the License, or (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++# MA 02111-1307 USA ++# ++ ++include $(TOPDIR)/config.mk ++ ++LIB = $(obj)lib$(SOC).a ++ ++COBJS = timer.o ether.o nand.o clock.o i2c.o ++SOBJS = lowlevel_init.o reset.o ++ ++SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) ++START := $(addprefix $(obj),$(START)) ++ ++all: $(obj).depend $(LIB) ++ ++$(LIB): $(OBJS) ++ $(AR) $(ARFLAGS) $@ $(OBJS) ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +Index: u-boot-2009.01/cpu/arm926ejs/da8xx/clock.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/cpu/arm926ejs/da8xx/clock.c +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc. <nsekhar@ti.com> ++ * ++ * DA8xx clock module ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ */ ++ ++#include <common.h> ++#include <asm/arch/hardware.h> ++ ++dv_reg_p sysdiv[9] = { ++ PLL0_DIV1, PLL0_DIV2, PLL0_DIV3, PLL0_DIV4, PLL0_DIV5, PLL0_DIV6, ++ PLL0_DIV7, PLL0_DIV8, PLL0_DIV9 }; ++ ++int clk_get(unsigned int id) ++{ ++ int pre_div = (REG(PLL0_PREDIV) & 0xff) + 1; ++ int pllm = REG(PLL0_PLLM) + 1; ++ int post_div = (REG(PLL0_POSTDIV) & 0xff) + 1; ++ int pll_out = CFG_OSCIN_FREQ; ++ ++ if(id == DAVINCI_AUXCLK_CLKID) ++ goto out; ++ ++ /* Lets keep this simple. Combining operations can result in ++ * unexpected approximations ++ */ ++ pll_out /= pre_div; ++ pll_out *= pllm; ++ ++ if(id == DAVINCI_PLLM_CLKID) ++ goto out; ++ ++ pll_out /= post_div; ++ ++ if(id == DAVINCI_PLLC_CLKID) ++ goto out; ++ ++ pll_out /= (REG(sysdiv[id - 1]) & 0xff) + 1; ++ ++out: ++ return pll_out; ++} +Index: u-boot-2009.01/cpu/arm926ejs/da8xx/ether.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/cpu/arm926ejs/da8xx/ether.c +@@ -0,0 +1,667 @@ ++/* ++ * Ethernet driver for TI TMS320DM644x (DaVinci) chips. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright ++ * follows: ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * dm644x_emac.c ++ * ++ * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM ++ * ++ * Copyright (C) 2005 Texas Instruments. ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ ++ * Modifications: ++ * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot. ++ * ver 1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors ++ * ++ */ ++#include <common.h> ++#include <command.h> ++#include <net.h> ++#include <miiphy.h> ++#include <asm/arch/emac_defs.h> ++ ++#ifdef CONFIG_DRIVER_TI_EMAC ++ ++#ifdef CONFIG_CMD_NET ++ ++unsigned int emac_dbg = 0; ++#define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args) ++ ++/* Internal static functions */ ++static int dm644x_eth_hw_init (void); ++static int dm644x_eth_open (void); ++static int dm644x_eth_close (void); ++static int dm644x_eth_send_packet (volatile void *packet, int length); ++static int dm644x_eth_rcv_packet (void); ++static void dm644x_eth_mdio_enable(void); ++ ++static int gen_init_phy(int phy_addr); ++static int gen_is_phy_connected(int phy_addr); ++static int gen_get_link_speed(int phy_addr); ++static int gen_auto_negotiate(int phy_addr); ++ ++/* Wrappers exported to the U-Boot proper */ ++int eth_hw_init(void) ++{ ++ return(dm644x_eth_hw_init()); ++} ++ ++int eth_init(bd_t * bd) ++{ ++ return(dm644x_eth_open()); ++} ++ ++void eth_halt(void) ++{ ++ dm644x_eth_close(); ++} ++ ++int eth_send(volatile void *packet, int length) ++{ ++ return(dm644x_eth_send_packet(packet, length)); ++} ++ ++int eth_rx(void) ++{ ++ return(dm644x_eth_rcv_packet()); ++} ++ ++void eth_mdio_enable(void) ++{ ++ dm644x_eth_mdio_enable(); ++} ++/* End of wrappers */ ++ ++/* dm644x_eth_mac_addr[0] goes out on the wire first */ ++ ++static u_int8_t dm644x_eth_mac_addr[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0x00 }; ++ ++/* ++ * This function must be called before emac_open() if you want to override ++ * the default mac address. ++ */ ++void dm644x_eth_set_mac_addr(const u_int8_t *addr) ++{ ++ int i; ++ ++ for (i = 0; i < sizeof (dm644x_eth_mac_addr); i++) { ++ dm644x_eth_mac_addr[i] = addr[i]; ++ } ++} ++ ++/* EMAC Addresses */ ++static volatile emac_regs *adap_emac = (emac_regs *)EMAC_BASE_ADDR; ++static volatile ewrap_regs *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR; ++static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR; ++ ++/* EMAC descriptors */ ++static volatile emac_desc *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE); ++static volatile emac_desc *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE); ++static volatile emac_desc *emac_rx_active_head = 0; ++static volatile emac_desc *emac_rx_active_tail = 0; ++static int emac_rx_queue_active = 0; ++ ++/* Receive packet buffers */ ++static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; ++ ++/* PHY address for a discovered PHY (0xff - not found) */ ++static volatile u_int8_t active_phy_addr = 0xff; ++ ++static int no_phy_init (int phy_addr) { return(1); } ++static int no_phy_is_connected (int phy_addr) { return(1); } ++static int no_phy_get_link_speed (int phy_addr) { return(1); } ++static int no_phy_auto_negotiate (int phy_addr) { return(1); } ++phy_t phy = { ++ .init = no_phy_init, ++ .is_phy_connected = no_phy_is_connected, ++ .get_link_speed = no_phy_get_link_speed, ++ .auto_negotiate = no_phy_auto_negotiate ++}; ++ ++static void dm644x_eth_mdio_enable(void) ++{ ++ u_int32_t clkdiv; ++ ++ clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; ++ ++ adap_mdio->CONTROL = (clkdiv & 0xff) | ++ MDIO_CONTROL_ENABLE | ++ MDIO_CONTROL_FAULT | ++ MDIO_CONTROL_FAULT_ENABLE; ++ ++ while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;} ++} ++ ++/* ++ * Tries to find an active connected PHY. Returns 1 if address if found. ++ * If no active PHY found returns 0. If more than one active PHY (switch) ++ * returns 2 ++ * Sets active_phy_addr variable when returns 1. ++ */ ++static int dm644x_eth_phy_detect(void) ++{ ++ u_int32_t phy_act_state; ++ int i; ++ ++ active_phy_addr = 0xff; ++ ++ if ((phy_act_state = adap_mdio->ALIVE) == 0) ++ return(0); /* No active PHYs */ ++ ++ debug_emac("dm644x_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state); ++ ++ for (i = 0; i < 32; i++) { ++ if (phy_act_state & (1 << i)) { ++ if (phy_act_state & ~(1 << i)) ++ return(2); /* More than one PHY */ ++ else { ++ active_phy_addr = i; ++ return(1); ++ } ++ } ++ } ++ ++ return(0); /* Just to make GCC happy */ ++} ++ ++ ++/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */ ++int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) ++{ ++ int tmp; ++ ++ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} ++ ++ adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO | ++ MDIO_USERACCESS0_WRITE_READ | ++ ((reg_num & 0x1f) << 21) | ++ ((phy_addr & 0x1f) << 16); ++ ++ /* Wait for command to complete */ ++ while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;} ++ ++ if (tmp & MDIO_USERACCESS0_ACK) { ++ *data = tmp & 0xffff; ++ return(1); ++ } ++ ++ *data = -1; ++ return(0); ++} ++ ++/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */ ++int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) ++{ ++ ++ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} ++ ++ adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO | ++ MDIO_USERACCESS0_WRITE_WRITE | ++ ((reg_num & 0x1f) << 21) | ++ ((phy_addr & 0x1f) << 16) | ++ (data & 0xffff); ++ ++ /* Wait for command to complete */ ++ while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} ++ ++ return(1); ++} ++ ++/* PHY functions for a generic PHY */ ++static int gen_init_phy(int phy_addr) ++{ ++ int ret = 1; ++ ++ if (gen_get_link_speed(phy_addr)) { ++ /* Try another time */ ++ ret = gen_get_link_speed(phy_addr); ++ } ++ ++ return(ret); ++} ++ ++static int gen_is_phy_connected(int phy_addr) ++{ ++ u_int16_t dummy; ++ ++ return(dm644x_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy)); ++} ++ ++static int gen_get_link_speed(int phy_addr) ++{ ++ u_int16_t tmp; ++ ++ if (dm644x_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04)) ++ return(1); ++ ++ return(0); ++} ++ ++static int gen_auto_negotiate(int phy_addr) ++{ ++ u_int16_t tmp; ++ ++ if (!dm644x_eth_phy_read(phy_addr, PHY_BMCR, &tmp)) ++ return(0); ++ ++ /* Restart Auto_negotiation */ ++ tmp |= PHY_BMCR_AUTON; ++ dm644x_eth_phy_write(phy_addr, PHY_BMCR, tmp); ++ ++ /*check AutoNegotiate complete */ ++ udelay (10000); ++ if (!dm644x_eth_phy_read(phy_addr, PHY_BMSR, &tmp)) ++ return(0); ++ ++ if (!(tmp & PHY_BMSR_AUTN_COMP)) ++ return(0); ++ ++ return(gen_get_link_speed(phy_addr)); ++} ++/* End of generic PHY functions */ ++ ++ ++#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) ++static int dm644x_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value) ++{ ++ return(dm644x_eth_phy_read(addr, reg, value) ? 0 : 1); ++} ++ ++static int dm644x_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value) ++{ ++ return(dm644x_eth_phy_write(addr, reg, value) ? 0 : 1); ++} ++ ++int dm644x_eth_miiphy_initialize(bd_t *bis) ++{ ++ miiphy_register(phy.name, dm644x_mii_phy_read, dm644x_mii_phy_write); ++ ++ return(1); ++} ++#endif ++ ++/* ++ * This function initializes the emac hardware. It does NOT initialize ++ * EMAC modules power or pin multiplexors, that is done by board_init() ++ * much earlier in bootup process. Returns 1 on success, 0 otherwise. ++ */ ++static int dm644x_eth_hw_init(void) ++{ ++ u_int32_t phy_id; ++ u_int16_t tmp; ++ int i, ret; ++ ++ /* The RMII clock can be sources internally through the SYSCLK7 ++ * or can come externally through a dedicated pin. This selection is ++ * controlled by PinMux9[21]. PinMux registers are off-limits for ARM. ++ * In short, we just assume there is a 50MHz RMII clock available. ++ */ ++ ++ dm644x_eth_mdio_enable(); ++ ++ for (i = 0; i < 256; i++) { ++ if (adap_mdio->ALIVE) ++ break; ++ udelay(1000); ++ } ++ ++ if (i >= 256) { ++ printf("No ETH PHY detected!!!\n"); ++ return(0); ++ } ++ ++ /* Find if a PHY is connected and get it's address */ ++ ret = dm644x_eth_phy_detect(); ++ ++ if (ret == 2) { ++ printf("More than one PHY detected.\n"); ++ return(1); ++ } else if(ret == 0) ++ return(0); ++ ++ /* Get PHY ID and initialize phy_ops for a detected PHY */ ++ if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) { ++ active_phy_addr = 0xff; ++ return(0); ++ } ++ ++ phy_id = (tmp << 16) & 0xffff0000; ++ ++ if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) { ++ active_phy_addr = 0xff; ++ return(0); ++ } ++ ++ phy_id |= tmp & 0x0000ffff; ++ ++ switch (phy_id) { ++ default: ++ sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr); ++ phy.init = gen_init_phy; ++ phy.is_phy_connected = gen_is_phy_connected; ++ phy.get_link_speed = gen_get_link_speed; ++ phy.auto_negotiate = gen_auto_negotiate; ++ } ++ ++ return(1); ++} ++ ++ ++/* Eth device open */ ++static int dm644x_eth_open(void) ++{ ++ dv_reg_p addr; ++ u_int32_t clkdiv, cnt; ++ volatile emac_desc *rx_desc; ++ int i; ++ ++ debug_emac("+ emac_open\n"); ++ ++ /* Reset EMAC module and disable interrupts in wrapper */ ++ adap_emac->SOFTRESET = 1; ++ while (adap_emac->SOFTRESET != 0) {;} ++ adap_ewrap->SOFTRESET = 1; ++ while (adap_ewrap->SOFTRESET != 0) {;} ++ ++ adap_ewrap->C0RXEN = adap_ewrap->C1RXEN = adap_ewrap->C2RXEN = 0; ++ adap_ewrap->C0TXEN = adap_ewrap->C1TXEN = adap_ewrap->C2TXEN = 0; ++ adap_ewrap->C0MISCEN = adap_ewrap->C1MISCEN = adap_ewrap->C2MISCEN = 0; ++ ++ rx_desc = emac_rx_desc; ++ ++ adap_emac->TXCONTROL = 0x01; ++ adap_emac->RXCONTROL = 0x01; ++ ++ /* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */ ++ /* Using channel 0 only - other channels are disabled */ ++ for (i = 0; i < 8; i++) { ++ adap_emac->MACINDEX = i; ++ adap_emac->MACADDRHI = ++ (dm644x_eth_mac_addr[3] << 24) | /* bits 23-16 */ ++ (dm644x_eth_mac_addr[2] << 16) | /* bits 31-24 */ ++ (dm644x_eth_mac_addr[1] << 8) | /* bits 39-32 */ ++ (dm644x_eth_mac_addr[0]); /* bits 47-40 */ ++ adap_emac->MACADDRLO = ++ (dm644x_eth_mac_addr[5] << 8) | /* bits 8-0*/ ++ (dm644x_eth_mac_addr[4]) | (1 << 19) | (1 << 20); /* bits 8-0 */ ++ } ++ ++ adap_emac->MACHASH1 = 0; ++ adap_emac->MACHASH2 = 0; ++ ++ /* Set source MAC address - REQUIRED for pause frames */ ++ adap_emac->MACSRCADDRHI = ++ (dm644x_eth_mac_addr[3] << 24) | /* bits 23-16 */ ++ (dm644x_eth_mac_addr[2] << 16) | /* bits 31-24 */ ++ (dm644x_eth_mac_addr[1] << 8) | /* bits 39-32 */ ++ (dm644x_eth_mac_addr[0]); /* bits 47-40 */ ++ adap_emac->MACSRCADDRLO = ++ (dm644x_eth_mac_addr[5] << 8) | /* bits 8-0 */ ++ (dm644x_eth_mac_addr[4]); /* bits 15-8 */ ++ ++ /* Set DMA 8 TX / 8 RX Head pointers to 0 */ ++ addr = &adap_emac->TX0HDP; ++ for(cnt = 0; cnt < 16; cnt++) ++ *addr++ = 0; ++ ++ addr = &adap_emac->TX0CP; ++ for(cnt = 0; cnt < 16; cnt++) ++ *addr++ = 0; ++ ++ /* Clear Statistics (do this before setting MacControl register) */ ++ addr = &adap_emac->RXGOODFRAMES; ++ for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++) ++ *addr++ = 0; ++ ++ /* No multicast addressing */ ++ adap_emac->MACHASH1 = 0; ++ adap_emac->MACHASH2 = 0; ++ ++ /* Create RX queue and set receive process in place */ ++ emac_rx_active_head = emac_rx_desc; ++ for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) { ++ rx_desc->next = (u_int32_t)(rx_desc + 1); ++ rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; ++ rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; ++ rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; ++ rx_desc++; ++ } ++ ++ /* Set the last descriptor's "next" parameter to 0 to end the RX desc list */ ++ rx_desc--; ++ rx_desc->next = 0; ++ emac_rx_active_tail = rx_desc; ++ emac_rx_queue_active = 1; ++ ++ /* Enable TX/RX */ ++ adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE; ++ adap_emac->RXBUFFEROFFSET = 0; ++ ++ /* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */ ++ adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN; ++ ++ /* Enable ch 0 only */ ++ adap_emac->RXUNICASTSET = 0x01; ++ ++ /* Enable MII interface and Full duplex mode */ ++ adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE) | EMAC_MACCONTROL_RMIISPEED_100; ++ ++ /* Init MDIO & get link state */ ++ clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; ++ adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT); ++ ++ if (!phy.get_link_speed(active_phy_addr)) ++ return(0); ++ ++ /* Start receive process */ ++ adap_emac->RX0HDP = (u_int32_t)emac_rx_desc; ++ ++ debug_emac("- emac_open\n"); ++ ++ return(1); ++} ++ ++/* EMAC Channel Teardown */ ++static void dm644x_eth_ch_teardown(int ch) ++{ ++ dv_reg dly = 0xff; ++ dv_reg cnt; ++ ++ debug_emac("+ emac_ch_teardown\n"); ++ ++ if (ch == EMAC_CH_TX) { ++ /* Init TX channel teardown */ ++ adap_emac->TXTEARDOWN = 1; ++ for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) { ++ /* Wait here for Tx teardown completion interrupt to occur ++ * Note: A task delay can be called here to pend rather than ++ * occupying CPU cycles - anyway it has been found that teardown ++ * takes very few cpu cycles and does not affect functionality */ ++ dly--; ++ udelay(1); ++ if (dly == 0) ++ break; ++ } ++ adap_emac->TX0CP = cnt; ++ adap_emac->TX0HDP = 0; ++ } else { ++ /* Init RX channel teardown */ ++ adap_emac->RXTEARDOWN = 1; ++ for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) { ++ /* Wait here for Rx teardown completion interrupt to occur ++ * Note: A task delay can be called here to pend rather than ++ * occupying CPU cycles - anyway it has been found that teardown ++ * takes very few cpu cycles and does not affect functionality */ ++ dly--; ++ udelay(1); ++ if (dly == 0) ++ break; ++ } ++ adap_emac->RX0CP = cnt; ++ adap_emac->RX0HDP = 0; ++ } ++ ++ debug_emac("- emac_ch_teardown\n"); ++} ++ ++/* Eth device close */ ++static int dm644x_eth_close(void) ++{ ++ debug_emac("+ emac_close\n"); ++ ++ dm644x_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */ ++ dm644x_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */ ++ ++ /* Reset EMAC module and disable interrupts in wrapper */ ++ adap_emac->SOFTRESET = 1; ++ adap_ewrap->SOFTRESET = 1; ++ ++ adap_ewrap->C0RXEN = adap_ewrap->C1RXEN = adap_ewrap->C2RXEN = 0; ++ adap_ewrap->C0TXEN = adap_ewrap->C1TXEN = adap_ewrap->C2TXEN = 0; ++ adap_ewrap->C0MISCEN = adap_ewrap->C1MISCEN = adap_ewrap->C2MISCEN = 0; ++ ++ debug_emac("- emac_close\n"); ++ return(1); ++} ++ ++static int tx_send_loop = 0; ++ ++/* ++ * This function sends a single packet on the network and returns ++ * positive number (number of bytes transmitted) or negative for error ++ */ ++static int dm644x_eth_send_packet(volatile void *packet, int length) ++{ ++ int ret_status = -1; ++ tx_send_loop = 0; ++ ++ /* Return error if no link */ ++ if (!phy.get_link_speed(active_phy_addr)) ++ { ++ printf("WARN: emac_send_packet: No link\n"); ++ return (ret_status); ++ } ++ ++ /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */ ++ if (length < EMAC_MIN_ETHERNET_PKT_SIZE) ++ { ++ length = EMAC_MIN_ETHERNET_PKT_SIZE; ++ } ++ ++ /* Populate the TX descriptor */ ++ emac_tx_desc->next = 0; ++ emac_tx_desc->buffer = (u_int8_t *)packet; ++ emac_tx_desc->buff_off_len = (length & 0xffff); ++ emac_tx_desc->pkt_flag_len = ((length & 0xffff) | ++ EMAC_CPPI_SOP_BIT | ++ EMAC_CPPI_OWNERSHIP_BIT | ++ EMAC_CPPI_EOP_BIT); ++ /* Send the packet */ ++ adap_emac->TX0HDP = (unsigned int)emac_tx_desc; ++ ++ /* Wait for packet to complete or link down */ ++ while (1) { ++ if (!phy.get_link_speed(active_phy_addr)) { ++ dm644x_eth_ch_teardown(EMAC_CH_TX); ++ return (ret_status); ++ } ++ if (adap_emac->TXINTSTATRAW & 0x01) { ++ ret_status = length; ++ break; ++ } ++ tx_send_loop++; ++ } ++ ++ return(ret_status); ++} ++ ++/* ++ * This function handles receipt of a packet from the network ++ */ ++static int dm644x_eth_rcv_packet(void) ++{ ++ volatile emac_desc *rx_curr_desc; ++ volatile emac_desc *curr_desc; ++ volatile emac_desc *tail_desc; ++ int status, ret = -1; ++ ++ rx_curr_desc = emac_rx_active_head; ++ status = rx_curr_desc->pkt_flag_len; ++ if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) { ++ if (status & EMAC_CPPI_RX_ERROR_FRAME) { ++ /* Error in packet - discard it and requeue desc */ ++ printf("WARN: emac_rcv_pkt: Error in packet\n"); ++ } else { ++ NetReceive(rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff)); ++ ret = rx_curr_desc->buff_off_len & 0xffff; ++ } ++ ++ /* Ack received packet descriptor */ ++ adap_emac->RX0CP = (unsigned int)rx_curr_desc; ++ curr_desc = rx_curr_desc; ++ emac_rx_active_head = (volatile emac_desc *)rx_curr_desc->next; ++ ++ if (status & EMAC_CPPI_EOQ_BIT) { ++ if (emac_rx_active_head) { ++ adap_emac->RX0HDP = (unsigned int)emac_rx_active_head; ++ } else { ++ emac_rx_queue_active = 0; ++ printf("INFO:emac_rcv_packet: RX Queue not active\n"); ++ } ++ } ++ ++ /* Recycle RX descriptor */ ++ rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; ++ rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; ++ rx_curr_desc->next = 0; ++ ++ if (emac_rx_active_head == 0) { ++ printf("INFO: emac_rcv_pkt: active queue head = 0\n"); ++ emac_rx_active_head = curr_desc; ++ emac_rx_active_tail = curr_desc; ++ if (emac_rx_queue_active != 0) { ++ adap_emac->RX0HDP = (unsigned int)emac_rx_active_head; ++ printf("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n"); ++ emac_rx_queue_active = 1; ++ } ++ } else { ++ tail_desc = emac_rx_active_tail; ++ emac_rx_active_tail = curr_desc; ++ tail_desc->next = (unsigned int)curr_desc; ++ status = tail_desc->pkt_flag_len; ++ if (status & EMAC_CPPI_EOQ_BIT) { ++ adap_emac->RX0HDP = (unsigned int)curr_desc; ++ status &= ~EMAC_CPPI_EOQ_BIT; ++ tail_desc->pkt_flag_len = status; ++ } ++ } ++ return(ret); ++ } ++ return(0); ++} ++ ++#endif /* CONFIG_CMD_NET */ ++ ++#endif /* CONFIG_DRIVER_TI_EMAC */ +Index: u-boot-2009.01/cpu/arm926ejs/da8xx/i2c.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/cpu/arm926ejs/da8xx/i2c.c +@@ -0,0 +1,356 @@ ++/* ++ * TI DaVinci (TMS320DM644x) I2C driver. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * -------------------------------------------------------- ++ * ++ * 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_DRIVER_DAVINCI_I2C ++ ++#include <i2c.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/i2c_defs.h> ++ ++#define CHECK_NACK() \ ++ do {\ ++ if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ ++ REG(I2C_CON) = 0;\ ++ return(1);\ ++ }\ ++ } while (0) ++ ++ ++static int wait_for_bus(void) ++{ ++ int stat, timeout; ++ ++ REG(I2C_STAT) = 0xffff; ++ ++ for (timeout = 0; timeout < 10; timeout++) { ++ if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) { ++ REG(I2C_STAT) = 0xffff; ++ return(0); ++ } ++ ++ REG(I2C_STAT) = stat; ++ udelay(50000); ++ } ++ ++ REG(I2C_STAT) = 0xffff; ++ return(1); ++} ++ ++ ++static int poll_i2c_irq(int mask) ++{ ++ int stat, timeout; ++ ++ for (timeout = 0; timeout < 10; timeout++) { ++ udelay(1000); ++ stat = REG(I2C_STAT); ++ if (stat & mask) { ++ return(stat); ++ } ++ } ++ ++ REG(I2C_STAT) = 0xffff; ++ return(stat | I2C_TIMEOUT); ++} ++ ++ ++void flush_rx(void) ++{ ++ int dummy; ++ ++ while (1) { ++ if (!(REG(I2C_STAT) & I2C_STAT_RRDY)) ++ break; ++ ++ dummy = REG(I2C_DRR); ++ REG(I2C_STAT) = I2C_STAT_RRDY; ++ udelay(1000); ++ } ++} ++ ++ ++void i2c_init(int speed, int slaveadd) ++{ ++ u_int32_t div, psc; ++ ++ if (REG(I2C_CON) & I2C_CON_EN) { ++ REG(I2C_CON) = 0; ++ udelay (50000); ++ } ++ ++ /* Get 1MHz into I2C internal */ ++ psc = CONFIG_SYS_HZ_CLOCK/1000000; ++ ++ div = CONFIG_SYS_HZ_CLOCK / (psc * speed); /* SCLL + SCLH */ ++ ++ REG(I2C_PSC) = psc - 1; /* 27MHz / (2 + 1) = 9MHz */ ++ REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */ ++ REG(I2C_SCLH) = div - REG(I2C_SCLL); ++ ++ REG(I2C_OA) = slaveadd; ++ REG(I2C_CNT) = 0; ++ ++ /* Interrupts must be enabled or I2C module won't work */ ++ REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | ++ I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; ++ ++ /* Now enable I2C controller (get it out of reset) */ ++ REG(I2C_CON) = I2C_CON_EN; ++ ++ udelay(1000); ++} ++ ++ ++int i2c_probe(u_int8_t chip) ++{ ++ int rc = 1; ++ ++ if (chip == REG(I2C_OA)) { ++ return(rc); ++ } ++ ++ REG(I2C_CON) = 0; ++ if (wait_for_bus()) {return(1);} ++ ++ /* try to read one byte from current (or only) address */ ++ REG(I2C_CNT) = 1; ++ REG(I2C_SA) = chip; ++ REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP | I2C_CON_FREE); ++ udelay (50000); ++ ++ if (!(REG(I2C_STAT) & I2C_STAT_NACK)) { ++ rc = 0; ++ flush_rx(); ++ REG(I2C_STAT) = 0xffff; ++ } else { ++ REG(I2C_STAT) = 0xffff; ++ REG(I2C_CON) |= I2C_CON_STP; ++ udelay(20000); ++ if (wait_for_bus()) {return(1);} ++ } ++ ++ flush_rx(); ++ REG(I2C_STAT) = 0xffff; ++ REG(I2C_CNT) = 0; ++ return(rc); ++} ++ ++ ++int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) ++{ ++ u_int32_t tmp; ++ int i; ++ ++ if ((alen < 0) || (alen > 2)) { ++ printf("%s(): bogus address length %x\n", __FUNCTION__, alen); ++ return(1); ++ } ++ ++ if (wait_for_bus()) {return(1);} ++ ++ if (alen != 0) { ++ /* Start address phase */ ++ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | ++ I2C_CON_FREE; ++ REG(I2C_CNT) = alen; ++ REG(I2C_SA) = chip; ++ REG(I2C_CON) = tmp; ++ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ switch (alen) { ++ case 2: ++ /* Send address MSByte */ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = (addr >> 8) & 0xff; ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ /* No break, fall through */ ++ case 1: ++ /* Send address LSByte */ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = addr & 0xff; ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); ++ ++ CHECK_NACK(); ++ ++ if (!(tmp & I2C_STAT_ARDY)) { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ } ++ } ++ ++ /* Address phase is over, now read 'len' bytes and stop */ ++ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP | I2C_CON_FREE; ++ REG(I2C_CNT) = len & 0xffff; ++ REG(I2C_SA) = chip; ++ REG(I2C_CON) = tmp; ++ ++ for (i = 0; i < len; i++) { ++ tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); ++ ++ CHECK_NACK(); ++ ++ if (tmp & I2C_STAT_RRDY) { ++ buf[i] = REG(I2C_DRR); ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ } ++ ++ tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (!(tmp & I2C_STAT_SCD)) { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ ++ flush_rx(); ++ REG(I2C_STAT) = 0xffff; ++ REG(I2C_CNT) = 0; ++ REG(I2C_CON) = 0; ++ ++ return(0); ++} ++ ++ ++int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) ++{ ++ u_int32_t tmp; ++ int i; ++ ++ if ((alen < 0) || (alen > 2)) { ++ printf("%s(): bogus address length %x\n", __FUNCTION__, alen); ++ return(1); ++ } ++ if (len < 0) { ++ printf("%s(): bogus length %x\n", __FUNCTION__, len); ++ return(1); ++ } ++ ++ if (wait_for_bus()) {return(1);} ++ ++ /* Start address phase */ ++ tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; ++ REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; ++ REG(I2C_SA) = chip; ++ REG(I2C_CON) = tmp; ++ ++ switch (alen) { ++ case 2: ++ /* Send address MSByte */ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = (addr >> 8) & 0xff; ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ /* No break, fall through */ ++ case 1: ++ /* Send address LSByte */ ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = addr & 0xff; ++ } else { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ } ++ ++ for (i = 0; i < len; i++) { ++ tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (tmp & I2C_STAT_XRDY) { ++ REG(I2C_DXR) = buf[i]; ++ } else { ++ return(1); ++ } ++ } ++ ++ tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); ++ ++ CHECK_NACK(); ++ ++ if (!(tmp & I2C_STAT_SCD)) { ++ REG(I2C_CON) = 0; ++ return(1); ++ } ++ ++ flush_rx(); ++ REG(I2C_STAT) = 0xffff; ++ REG(I2C_CNT) = 0; ++ REG(I2C_CON) = 0; ++ ++ return(0); ++} ++ ++#if 0 ++u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg) ++{ ++ u_int8_t tmp; ++ ++ i2c_read(chip, reg, 1, &tmp, 1); ++ return(tmp); ++} ++ ++ ++void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val) ++{ ++ u_int8_t tmp; ++ ++ i2c_write(chip, reg, 1, &tmp, 1); ++} ++#endif /* if 0 */ ++ ++#endif /* CONFIG_DRIVER_DAVINCI_I2C */ +Index: u-boot-2009.01/cpu/arm926ejs/da8xx/lowlevel_init.S +=================================================================== +--- /dev/null ++++ u-boot-2009.01/cpu/arm926ejs/da8xx/lowlevel_init.S +@@ -0,0 +1,504 @@ ++/* ++ * Low-level board setup code for TI DA8xx SoC based boards. ++ * ++ * Copyright (C) 2008 Texas Instruments, Inc <www.ti.com> ++ * Sekhar Nori <nsekhar@ti.com> ++ * ++ * Based on TI DaVinci low level init code. Original copyrights follow. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Partially based on TI sources, original copyrights follow: ++ */ ++ ++/* ++ * Board specific setup info ++ * ++ * (C) Copyright 2003 ++ * Texas Instruments, <www.ti.com> ++ * Kshitij Gupta <Kshitij@ti.com> ++ * ++ * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004 ++ * ++ * Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004 ++ * See file CREDITS for list of people who contributed to this ++ * project. ++ * ++ * Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005 ++ * See file CREDITS for list of people who contributed to this ++ * project. ++ * ++ * Modified for DV-EVM board by Swaminathan S, Nov 2005 ++ * See file CREDITS for list of people who contributed to this ++ * project. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#include <config.h> ++#include <asm/arch/hardware.h> ++ ++.globl lowlevel_init ++lowlevel_init: ++ ++ nop ++ nop ++ nop ++ nop ++ ++ /* ++ * Call board-specific lowlevel init. ++ * That MUST be present and THAT returns ++ * back to arch calling code with "mov pc, lr." ++ */ ++ b dv_board_init ++ ++#ifndef CONFIG_USE_IRQ ++ /*-------------------------------------------------------* ++ * Mask all IRQs by clearing the global enable and setting ++ * the enable clear for all the 90 interrupts. ++ *-------------------------------------------------------*/ ++ mov r1, $0 ++ ldr r0, INTC_GLB_EN_ADDR ++ str r1, [r0] ++ ++ ldr r0, INTC_HINT_EN_ADDR ++ str r1, [r0] ++ add r0, r0, $4 ++ str r1, [r0] ++ add r0, r0, $4 ++ str r1, [r0] ++ ++ mvn r1, r1 ++ ldr r0, INTC_EN_CLR0_ADDR ++ str r1, [r0] ++ add r0, r0, $4 ++ str r1, [r0] ++ add r0, r0, $4 ++ str r1, [r0] ++#endif ++ ++ /*------------------------------------------------------* ++ * PLL0 Initialization - works only in non-secure devices ++ *------------------------------------------------------*/ ++ ++ /* TODO: Write the kick values and the PLL master lock bits */ ++ ++ /* Select OSCIN in clockmode bit in PLLCTL register. This is the only ++ * clock mode supported on DA8xx ++ */ ++ ldr r6, PLL0_PLLCTL_ADDR ++ ldr r7, PLL_CLKSRC_MASK ++ ldr r8, [r6] ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Clear the PLLENSRC bit in PLLCTL */ ++ ldr r7, PLL_ENSRC_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Bypass the PLL */ ++ ldr r7, PLL_BYPASS_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */ ++ mov r10, $0x20 ++WaitPLL0Loop: ++ subs r10, r10, $1 ++ bne WaitPLL0Loop ++ ++ /* Reset the PLL */ ++ ldr r7, PLL_RESET_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* disable PLL output */ ++ mov r7, $0x10 ++ orr r8, r8, r7 ++ str r8, [r6] ++ ++ /* Power up the PLL */ ++ ldr r7, PLL_PWRUP_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Enable the PLL from Disable Mode */ ++ ldr r7, PLL_DISABLE_ENABLE_MASK ++ and r8, r8, r7 ++ str r8, [r6] ++ ++ /* Wait for the PLL stabilization time - 150us assumed */ ++ mov r10, $0xE10 ++PLLStableLoop: ++ subs r10, r10, $1 ++ bne PLLStableLoop ++ ++ /* Program the PLL Multiplier */ ++ ldr r6, PLL0_PLLM_ADDR ++ mov r2, $0x18 /* 24 * 25 = 600MHz*/ ++ str r2, [r6] ++ ++ /* Program the POSTDIV Value */ ++ ldr r6, PLL0_POSTDIV_ADDR ++ mov r3, $0x01 ++ mov r3, r3, lsl $15 ++ orr r3, r3, $0x01 ++ str r3, [r6] ++ ++ /* Program the SYSCLKx dividedrs */ ++ ++ /* Following defaults are good: ++ * SYSCLK1 = /1 => 300MHz GEM ++ * SYSCLK2 = /2 => 150MHz EDMA, MMC/SD, UART1/2, SPI1 ++ * SYSCLK3 = /3 => 100MHz Possible EMIF2.5 ++ * SYSCLK4 = /4 => 75MHz INTC, PSC, EMAC, USB 1.1, I2C1 ++ * SYSCLK5 = /3 => 100MHz Possible EMIF3.0 (use DIV4p5) ++ * SYSCLK6 = /1 => 300MHz ARM ++ * SYSCLK7 = /6 => 50MHz RMII Ref Clk ++ * SYSCLK8 = /6 => 50MHz Dont use ++ * SYSCLK9 = /6 => 50MHz Dont use ++ * AUXCLK FIXED => 24Mhz Timer 0/1, 12C0, McASP AuxClk ++ */ ++ ++ /* Wait for PLL to Reset Properly - 128 OSCIN cycles*/ ++ mov r10, $128 ++ResetPPL2Loop: ++ subs r10, r10, $1 ++ bne ResetPPL2Loop ++ ++ /* Bring PLL out of Reset */ ++ ldr r6, PLL0_PLLCTL_ADDR ++ ldr r8, [r6] ++ orr r8, r8, $0x08 ++ str r8, [r6] ++ ++ /* Wait for PLL to Lock */ ++ ldr r10, PLL_LOCK_COUNT ++PLL0Lock: ++ subs r10, r10, $1 ++ bne PLL0Lock ++ ++ /* Enable the PLL */ ++ ldr r6, PLL0_PLLCTL_ADDR ++ ldr r8, [r6] ++ orr r8, r8, $0x01 ++ str r8, [r6] ++ ++ /*------------------------------------------------------* ++ * Setup the pinmux for DDR2 * ++ *------------------------------------------------------*/ ++ ++ ldr r0, PINMUX1_ADDR ++ ldr r1, PINMUX1_VAL ++ str r1, [r0] ++ ++ ldr r0, PINMUX2_ADDR ++ ldr r1, PINMUX2_VAL ++ str r1, [r0] ++ ++ ldr r0, PINMUX5_ADDR ++ ldr r1, PINMUX5_VAL ++ str r1, [r0] ++ ++ ldr r0, PINMUX6_ADDR ++ ldr r1, PINMUX6_VAL ++ str r1, [r0] ++ ++ ldr r8, PINMUX7_FLAG_CLEAR ++ ldr r7, PINMUX7_VAL ++ ldr r0, PINMUX7_ADDR ++ ldr r1, [r0] ++ and r1, r1, r8 ++ orr r1, r1, r7 ++ str r1, [r0] ++ ++ ++ /*------------------------------------------------------* ++ * Get the EMIF3 out of reset * ++ *------------------------------------------------------*/ ++ ++ /* Shut down the DDR2 LPSC Module */ ++ ldr r8, PSC_FLAG_CLEAR ++ ldr r6, MDCTL_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, r8 ++ orr r7, r7, $0x03 ++ str r7, [r6] ++ ++ /* Enable the Power Domain Transition Command */ ++ ldr r6, PSC1_PTCMD_ADDR ++ ldr r7, [r6] ++ orr r7, r7, $0x01 ++ str r7, [r6] ++ ++ /* Check for Transition Complete(PTSTAT) */ ++checkStatClkStop0: ++ ldr r6, PSC1_PTSTAT_ADDR ++ ldr r7, [r6] ++ ands r7, r7, $0x01 ++ bne checkStatClkStop0 ++ ++ /* Check for DDR2 Controller Enable Completion */ ++checkDDRStatClkStop0: ++ ldr r6, MDSTAT_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, $0x1f ++ cmp r7, $0x03 ++ bne checkDDRStatClkStop0 ++ ++ /*------------------------------------------------------* ++ * Put the EMIF3 in reset * ++ *------------------------------------------------------*/ ++ ++ /* Shut down the DDR2 LPSC Module */ ++ ldr r8, PSC_FLAG_CLEAR ++ ldr r6, MDCTL_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, r8 ++ orr r7, r7, $0x01 ++ str r7, [r6] ++ ++ /* Enable the Power Domain Transition Command */ ++ ldr r6, PSC1_PTCMD_ADDR ++ ldr r7, [r6] ++ orr r7, r7, $0x01 ++ str r7, [r6] ++ ++ /* Check for Transition Complete(PTSTAT) */ ++checkStatClkStop1: ++ ldr r6, PSC1_PTSTAT_ADDR ++ ldr r7, [r6] ++ ands r7, r7, $0x01 ++ bne checkStatClkStop1 ++ ++ /* Check for DDR2 Controller Enable Completion */ ++checkDDRStatClkStop1: ++ ldr r6, MDSTAT_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, $0x1f ++ cmp r7, $0x01 ++ bne checkDDRStatClkStop1 ++ ++ nop ++ nop ++ ++ /*------------------------------------------------------* ++ * Get the EMIF3 out of reset * ++ *------------------------------------------------------*/ ++ ++ /* Shut down the DDR2 LPSC Module */ ++ ldr r8, PSC_FLAG_CLEAR ++ ldr r6, MDCTL_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, r8 ++ orr r7, r7, $0x03 ++ str r7, [r6] ++ ++ /* Enable the Power Domain Transition Command */ ++ ldr r6, PSC1_PTCMD_ADDR ++ ldr r7, [r6] ++ orr r7, r7, $0x01 ++ str r7, [r6] ++ ++ /* Check for Transition Complete(PTSTAT) */ ++checkStatClkStop2: ++ ldr r6, PSC1_PTSTAT_ADDR ++ ldr r7, [r6] ++ ands r7, r7, $0x01 ++ bne checkStatClkStop2 ++ ++ /* Check for DDR2 Controller Enable Completion */ ++checkDDRStatClkStop2: ++ ldr r6, MDSTAT_EMIF3 ++ ldr r7, [r6] ++ and r7, r7, $0x1f ++ cmp r7, $0x03 ++ bne checkDDRStatClkStop2 ++ ++ nop ++ nop ++ ++ /*-----------------------------------------------------* ++ * Wait before programing the SDRAM timimg values * ++ *-----------------------------------------------------*/ ++ ++ ldr r10, EMIF3_TIMING_WAIT_VAL ++emif3TimingWait: ++ sub r10, r10, $0x1 ++ cmp r10, $0x0 ++ bne emif3TimingWait ++ ++ /*------------------------------------------------------* ++ * Program EMIF3 MMRs for 133MHz SDRAM Setting * ++ *------------------------------------------------------*/ ++ ++ /* Program SDRAM Bank Config Register */ ++ ldr r6, SDCFG ++ ldr r7, SDCFG_VAL ++ str r7, [r6] ++ ++ /* Program SDRAM TIM-0 Config Register */ ++ ldr r6, SDTIM0 ++ ldr r7, SDTIM0_VAL_162MHz ++ str r7, [r6] ++ ++ /* Program SDRAM TIM-1 Config Register */ ++ ldr r6, SDTIM1 ++ ldr r7, SDTIM1_VAL_162MHz ++ str r7, [r6] ++ ++ /* Program the SDRAM Bank Config Control Register */ ++ ldr r10, MASK_VAL ++ ldr r8, SDCFG ++ ldr r9, SDCFG_VAL ++ and r9, r9, r10 ++ str r9, [r8] ++ ++ /* Program SDRAM SDREF Config Register */ ++ ldr r6, SDREF ++ ldr r7, SDREF_VAL ++ str r7, [r6] ++ ++ /* Issue a Dummy DDR2 read/write */ ++ ldr r8, DDR2_START_ADDR ++ ldr r7, DUMMY_VAL ++ str r7, [r8] ++ ldr r7, [r8] ++ ++ /* DDR Writes and Reads */ ++ ldr r6, CFGTEST ++ mov r3, $0x01 ++ str r3, [r6] ++ ++ nop ++ nop ++ nop ++ nop ++ ++ /* ++ * Call board-specific lowlevel init. ++ * That MUST be present and THAT returns ++ * back to arch calling code with "mov pc, lr." ++ */ ++ b dv_board_init ++ ++.ltorg ++ ++PINMUX1_ADDR: ++ .word PINMUX1 ++PINMUX2_ADDR: ++ .word PINMUX2 ++PINMUX5_ADDR: ++ .word PINMUX5 ++PINMUX6_ADDR: ++ .word PINMUX6 ++PINMUX7_ADDR: ++ .word PINMUX7 ++PINMUX1_VAL: ++ .word 0x11111111 ++PINMUX2_VAL: ++ .word 0x01111111 ++PINMUX5_VAL: ++ .word 0x11111110 ++PINMUX6_VAL: ++ .word 0x11111111 ++PINMUX7_FLAG_CLEAR: ++ .word 0xFFFFF000 ++PINMUX7_VAL: ++ .word 0x111 ++ ++ ++MDCTL_EMIF3: ++ .word PSC1_MDCTL + 4 * 6 ++MDSTAT_EMIF3: ++ .word PSC1_MDSTAT + 4 * 6 ++ ++PSC1_PTCMD_ADDR: ++ .word PSC1_PTCMD ++PSC1_PTSTAT_ADDR: ++ .word PSC1_PTSTAT ++ ++INTC_GLB_EN_ADDR: ++ .word INTC_GLB_EN ++INTC_EN_CLR0_ADDR: ++ .word INTC_EN_CLR0 ++INTC_HINT_EN_ADDR: ++ .word INTC_HINT_EN ++ ++PSC_FLAG_CLEAR: ++ .word 0xffffffe0 ++PSC_GEM_FLAG_CLEAR: ++ .word 0xfffffeff ++ ++/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */ ++SDREF: ++ .word DAVINCI_DDR_EMIF_CTRL_BASE + 0xc ++SDREF_VAL: ++ .word 0x000005c3 ++SDCFG: ++ .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x8 ++SDCFG_VAL: ++#ifdef SDRAM_4BANKS_10COLS ++ .word 0x00178622 ++#elif defined SDRAM_8BANKS_10COLS ++ .word 0x00178632 ++#else ++#error "Unknown SDRAM configuration!!!" ++#endif ++SDTIM0: ++ .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x10 ++SDTIM0_VAL_162MHz: ++ .word 0x28923211 ++SDTIM1: ++ .word DAVINCI_DDR_EMIF_CTRL_BASE + 0x14 ++SDTIM1_VAL_162MHz: ++ .word 0x0016c722 ++CFGTEST: ++ .word DAVINCI_DDR_EMIF_DATA_BASE + 0x10000 ++MASK_VAL: ++ .word 0x00000fff ++EMIF3_TIMING_WAIT_VAL: ++ .word 990000 ++ ++PLL_CLKSRC_MASK: ++ .word 0xfffffeff /* Mask the Clock Mode bit */ ++PLL_ENSRC_MASK: ++ .word 0xffffffdf /* Select the PLLEN source */ ++PLL_BYPASS_MASK: ++ .word 0xfffffffe /* Put the PLL in BYPASS */ ++PLL_RESET_MASK: ++ .word 0xfffffff7 /* Put the PLL in Reset Mode */ ++PLL_PWRUP_MASK: ++ .word 0xfffffffd /* PLL Power up Mask Bit */ ++PLL_DISABLE_ENABLE_MASK: ++ .word 0xffffffef /* Enable the PLL from Disable */ ++PLL_LOCK_COUNT: ++ .word 2000 ++ ++/* PLL0 MMRs */ ++PLL0_PLLCTL_ADDR: ++ .word PLL0_PLLCTL ++PLL0_PLLM_ADDR: ++ .word PLL0_PLLM ++PLL0_POSTDIV_ADDR: ++ .word PLL0_POSTDIV ++ ++DDR2_START_ADDR: ++ .word 0xc0000000 ++DUMMY_VAL: ++ .word 0xa55aa55a +Index: u-boot-2009.01/cpu/arm926ejs/da8xx/nand.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/cpu/arm926ejs/da8xx/nand.c +@@ -0,0 +1,475 @@ ++/* ++ * NAND driver for TI DaVinci based boards. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Based on Linux DaVinci NAND driver by TI. Original copyright follows: ++ */ ++ ++/* ++ * ++ * linux/drivers/mtd/nand/nand_davinci.c ++ * ++ * NAND Flash Driver ++ * ++ * Copyright (C) 2006 Texas Instruments. ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ * ++ * Overview: ++ * This is a device driver for the NAND flash device found on the ++ * DaVinci board which utilizes the Samsung k9k2g08 part. ++ * ++ Modifications: ++ ver. 1.0: Feb 2005, Vinod/Sudhakar ++ - ++ * ++ */ ++ ++#include <common.h> ++#include <asm/io.h> ++ ++#ifdef CONFIG_SYS_USE_NAND ++#if !defined(CONFIG_NAND_LEGACY) ++ ++#include <nand.h> ++#include <asm/arch/nand_defs.h> ++#include <asm/arch/emif_defs.h> ++ ++extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE]; ++ ++static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) ++{ ++ struct nand_chip *this = mtd->priv; ++ u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W; ++ ++ IO_ADDR_W &= ~(MASK_ALE|MASK_CLE); ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ if ( ctrl & NAND_CLE ) ++ IO_ADDR_W |= MASK_CLE; ++ if ( ctrl & NAND_ALE ) ++ IO_ADDR_W |= MASK_ALE; ++ this->IO_ADDR_W = (void __iomem *) IO_ADDR_W; ++ } ++ ++ if (cmd != NAND_CMD_NONE) ++ writeb(cmd, this->IO_ADDR_W); ++} ++ ++/* Set WP on deselect, write enable on select */ ++static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) ++{ ++#define GPIO_SET_DATA01 0x01c67018 ++#define GPIO_CLR_DATA01 0x01c6701c ++#define GPIO_NAND_WP (1 << 4) ++#ifdef SONATA_BOARD_GPIOWP ++ if (chip < 0) { ++ REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP; ++ } else { ++ REG(GPIO_SET_DATA01) |= GPIO_NAND_WP; ++ } ++#endif ++} ++ ++#ifdef CONFIG_SYS_NAND_HW_ECC ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++/* Linux-compatible ECC uses MTD defaults. */ ++/* These layouts are not compatible with Linux or RBL/UBL. */ ++#ifdef CONFIG_SYS_NAND_LARGEPAGE ++static struct nand_ecclayout davinci_nand_ecclayout = { ++ .eccbytes = 12, ++ .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, ++ .oobfree = { ++ {.offset = 2, .length = 6}, ++ {.offset = 12, .length = 12}, ++ {.offset = 28, .length = 12}, ++ {.offset = 44, .length = 12}, ++ {.offset = 60, .length = 4} ++ } ++}; ++#elif defined(CONFIG_SYS_NAND_SMALLPAGE) ++static struct nand_ecclayout davinci_nand_ecclayout = { ++ .eccbytes = 3, ++ .eccpos = {0, 1, 2}, ++ .oobfree = { ++ {.offset = 6, .length = 2}, ++ {.offset = 8, .length = 8} ++ } ++}; ++#else ++#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" ++#endif ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ ++static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) ++{ ++ emifregs emif_addr; ++ int dummy; ++ ++ emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; ++ ++ dummy = emif_addr->NANDF1ECC; ++ dummy = emif_addr->NANDF2ECC; ++ dummy = emif_addr->NANDF3ECC; ++ dummy = emif_addr->NANDF4ECC; ++ ++ emif_addr->NANDFCR |= (1 << 8); ++} ++ ++static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) ++{ ++ u_int32_t ecc = 0; ++ emifregs emif_base_addr; ++ ++ emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; ++ ++ if (region == 1) ++ ecc = emif_base_addr->NANDF1ECC; ++ else if (region == 2) ++ ecc = emif_base_addr->NANDF2ECC; ++ else if (region == 3) ++ ecc = emif_base_addr->NANDF3ECC; ++ else if (region == 4) ++ ecc = emif_base_addr->NANDF4ECC; ++ ++ return(ecc); ++} ++ ++static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) ++{ ++ u_int32_t tmp; ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++ /* ++ * This is not how you should read ECCs on large page Davinci devices. ++ * The region parameter gets you ECCs for flash chips on different chip ++ * selects, not the 4x512 byte pages in a 2048 byte page. ++ * ++ * Preserved for backwards compatibility though. ++ */ ++ ++ int region, n; ++ struct nand_chip *this = mtd->priv; ++ ++ n = (this->ecc.size/512); ++ ++ region = 1; ++ while (n--) { ++ tmp = nand_davinci_readecc(mtd, region); ++ *ecc_code++ = tmp; ++ *ecc_code++ = tmp >> 16; ++ *ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0); ++ region++; ++ } ++#else ++ const int region = 1; ++ ++ tmp = nand_davinci_readecc(mtd, region); ++ ++ /* Squeeze 4 bytes ECC into 3 bytes by removing RESERVED bits ++ * and shifting. RESERVED bits are 31 to 28 and 15 to 12. */ ++ tmp = (tmp & 0x00000fff) | ((tmp & 0x0fff0000) >> 4); ++ ++ /* Invert so that erased block ECC is correct */ ++ tmp = ~tmp; ++ ++ *ecc_code++ = tmp; ++ *ecc_code++ = tmp >> 8; ++ *ecc_code++ = tmp >> 16; ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ return(0); ++} ++ ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf) ++{ ++ u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8); ++ ++ ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp)); ++ ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp)); ++ ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp)); ++} ++ ++static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data) ++{ ++ u_int32_t i; ++ u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8]; ++ u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8]; ++ u_int8_t ecc_bit[24]; ++ u_int8_t ecc_sum = 0; ++ u_int8_t find_bit = 0; ++ u_int32_t find_byte = 0; ++ int is_ecc_ff; ++ ++ is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff)); ++ ++ nand_davinci_gen_true_ecc(ecc_nand); ++ nand_davinci_gen_true_ecc(ecc_calc); ++ ++ for (i = 0; i <= 2; i++) { ++ *(ecc_nand + i) = ~(*(ecc_nand + i)); ++ *(ecc_calc + i) = ~(*(ecc_calc + i)); ++ } ++ ++ for (i = 0; i < 8; i++) { ++ tmp0_bit[i] = *ecc_nand % 2; ++ *ecc_nand = *ecc_nand / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ tmp1_bit[i] = *(ecc_nand + 1) % 2; ++ *(ecc_nand + 1) = *(ecc_nand + 1) / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ tmp2_bit[i] = *(ecc_nand + 2) % 2; ++ *(ecc_nand + 2) = *(ecc_nand + 2) / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ comp0_bit[i] = *ecc_calc % 2; ++ *ecc_calc = *ecc_calc / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ comp1_bit[i] = *(ecc_calc + 1) % 2; ++ *(ecc_calc + 1) = *(ecc_calc + 1) / 2; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ comp2_bit[i] = *(ecc_calc + 2) % 2; ++ *(ecc_calc + 2) = *(ecc_calc + 2) / 2; ++ } ++ ++ for (i = 0; i< 6; i++) ++ ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2]; ++ ++ for (i = 0; i < 8; i++) ++ ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i]; ++ ++ for (i = 0; i < 8; i++) ++ ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i]; ++ ++ ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0]; ++ ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1]; ++ ++ for (i = 0; i < 24; i++) ++ ecc_sum += ecc_bit[i]; ++ ++ switch (ecc_sum) { ++ case 0: ++ /* Not reached because this function is not called if ++ ECC values are equal */ ++ return 0; ++ case 1: ++ /* Uncorrectable error */ ++ MTDDEBUG (MTD_DEBUG_LEVEL0, ++ "ECC UNCORRECTED_ERROR 1\n"); ++ return(-1); ++ case 12: ++ /* Correctable error */ ++ find_byte = (ecc_bit[23] << 8) + ++ (ecc_bit[21] << 7) + ++ (ecc_bit[19] << 6) + ++ (ecc_bit[17] << 5) + ++ (ecc_bit[15] << 4) + ++ (ecc_bit[13] << 3) + ++ (ecc_bit[11] << 2) + ++ (ecc_bit[9] << 1) + ++ ecc_bit[7]; ++ ++ find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; ++ ++ MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC " ++ "error at offset: %d, bit: %d\n", ++ find_byte, find_bit); ++ ++ page_data[find_byte] ^= (1 << find_bit); ++ ++ return(0); ++ default: ++ if (is_ecc_ff) { ++ if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0) ++ return(0); ++ } ++ MTDDEBUG (MTD_DEBUG_LEVEL0, ++ "UNCORRECTED_ERROR default\n"); ++ return(-1); ++ } ++} ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ ++static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) ++{ ++ struct nand_chip *this = mtd->priv; ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++ int block_count = 0, i, rc; ++ ++ block_count = (this->ecc.size/512); ++ for (i = 0; i < block_count; i++) { ++ if (memcmp(read_ecc, calc_ecc, 3) != 0) { ++ rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat); ++ if (rc < 0) { ++ return(rc); ++ } ++ } ++ read_ecc += 3; ++ calc_ecc += 3; ++ dat += 512; ++ } ++#else ++ u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) | ++ (read_ecc[2] << 16); ++ u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) | ++ (calc_ecc[2] << 16); ++ u_int32_t diff = ecc_calc ^ ecc_nand; ++ ++ if (diff) { ++ if ((((diff >> 12) ^ diff) & 0xfff) == 0xfff) { ++ /* Correctable error */ ++ if ((diff >> (12 + 3)) < this->ecc.size) { ++ uint8_t find_bit = 1 << ((diff >> 12) & 7); ++ uint32_t find_byte = diff >> (12 + 3); ++ ++ dat[find_byte] ^= find_bit; ++ MTDDEBUG(MTD_DEBUG_LEVEL0, "Correcting single " ++ "bit ECC error at offset: %d, bit: " ++ "%d\n", find_byte, find_bit); ++ return 1; ++ } else { ++ return -1; ++ } ++ } else if (!(diff & (diff - 1))) { ++ /* Single bit ECC error in the ECC itself, ++ nothing to fix */ ++ MTDDEBUG(MTD_DEBUG_LEVEL0, "Single bit ECC error in " ++ "ECC.\n"); ++ return 1; ++ } else { ++ /* Uncorrectable error */ ++ MTDDEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n"); ++ return -1; ++ } ++ } ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ return(0); ++} ++#endif /* CONFIG_SYS_NAND_HW_ECC */ ++ ++static int nand_davinci_dev_ready(struct mtd_info *mtd) ++{ ++ emifregs emif_addr; ++ ++ emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; ++ ++ return(emif_addr->NANDFSR & 0x1); ++} ++ ++static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this) ++{ ++ while(!nand_davinci_dev_ready(mtd)) {;} ++ *NAND_CE0CLE = NAND_STATUS; ++ return(*NAND_CE0DATA); ++} ++ ++static void nand_flash_init(void) ++{ ++ u_int32_t acfg1 = 0x3ffffffc; ++ u_int32_t acfg2 = 0x3ffffffc; ++ u_int32_t acfg3 = 0x3ffffffc; ++ u_int32_t acfg4 = 0x3ffffffc; ++ emifregs emif_regs; ++ ++ /*------------------------------------------------------------------* ++ * NAND FLASH CHIP TIMEOUT @ 459 MHz * ++ * * ++ * AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz * ++ * AEMIF.CLK period = 1/76.5 MHz = 13.1 ns * ++ * * ++ *------------------------------------------------------------------*/ ++ acfg1 = 0 ++ | (0 << 31 ) /* selectStrobe */ ++ | (0 << 30 ) /* extWait */ ++ | (1 << 26 ) /* writeSetup 10 ns */ ++ | (3 << 20 ) /* writeStrobe 40 ns */ ++ | (1 << 17 ) /* writeHold 10 ns */ ++ | (1 << 13 ) /* readSetup 10 ns */ ++ | (5 << 7 ) /* readStrobe 60 ns */ ++ | (1 << 4 ) /* readHold 10 ns */ ++ | (3 << 2 ) /* turnAround ?? ns */ ++ | (0 << 0 ) /* asyncSize 8-bit bus */ ++ ; ++ ++ emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; ++ ++ emif_regs->AWCCR |= 0x10000000; ++ emif_regs->AB1CR = acfg1; /* 0x08244128 */; ++ emif_regs->AB2CR = acfg2; ++ emif_regs->AB3CR = acfg3; ++ emif_regs->AB4CR = acfg4; ++ emif_regs->NANDFCR = 0x00000101; ++} ++ ++int board_nand_init(struct nand_chip *nand) ++{ ++ nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA; ++ nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA; ++ nand->chip_delay = 0; ++ nand->select_chip = nand_davinci_select_chip; ++#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT ++ nand->options = NAND_USE_FLASH_BBT; ++#endif ++#ifdef CONFIG_SYS_NAND_HW_ECC ++ nand->ecc.mode = NAND_ECC_HW; ++#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC ++ nand->ecc.layout = &davinci_nand_ecclayout; ++#ifdef CONFIG_SYS_NAND_LARGEPAGE ++ nand->ecc.size = 2048; ++ nand->ecc.bytes = 12; ++#elif defined(CONFIG_SYS_NAND_SMALLPAGE) ++ nand->ecc.size = 512; ++ nand->ecc.bytes = 3; ++#else ++#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!" ++#endif ++#else ++ nand->ecc.size = 512; ++ nand->ecc.bytes = 3; ++#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */ ++ nand->ecc.calculate = nand_davinci_calculate_ecc; ++ nand->ecc.correct = nand_davinci_correct_data; ++ nand->ecc.hwctl = nand_davinci_enable_hwecc; ++#else ++ nand->ecc.mode = NAND_ECC_SOFT; ++#endif /* CONFIG_SYS_NAND_HW_ECC */ ++ ++ /* Set address of hardware control function */ ++ nand->cmd_ctrl = nand_davinci_hwcontrol; ++ ++ nand->dev_ready = nand_davinci_dev_ready; ++ nand->waitfunc = nand_davinci_waitfunc; ++ ++ nand_flash_init(); ++ ++ return(0); ++} ++ ++#else ++#error "U-Boot legacy NAND support not available for DaVinci chips" ++#endif ++#endif /* CONFIG_SYS_USE_NAND */ +Index: u-boot-2009.01/cpu/arm926ejs/da8xx/reset.S +=================================================================== +--- /dev/null ++++ u-boot-2009.01/cpu/arm926ejs/da8xx/reset.S +@@ -0,0 +1,77 @@ ++/* ++ * Processor reset using WDT for TI TMS320DM644x SoC. ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * ----------------------------------------------------- ++ * ++ * 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 ++ */ ++ ++.globl reset_cpu ++reset_cpu: ++ ldr r0, WDT_TGCR ++ mov r1, $0x08 ++ str r1, [r0] ++ ldr r1, [r0] ++ orr r1, r1, $0x03 ++ str r1, [r0] ++ mov r1, $0 ++ ldr r0, WDT_TIM12 ++ str r1, [r0] ++ ldr r0, WDT_TIM34 ++ str r1, [r0] ++ ldr r0, WDT_PRD12 ++ str r1, [r0] ++ ldr r0, WDT_PRD34 ++ str r1, [r0] ++ ldr r0, WDT_TCR ++ ldr r1, [r0] ++ orr r1, r1, $0x40 ++ str r1, [r0] ++ ldr r0, WDT_WDTCR ++ ldr r1, [r0] ++ orr r1, r1, $0x4000 ++ str r1, [r0] ++ ldr r1, WDTCR_VAL1 ++ str r1, [r0] ++ ldr r1, WDTCR_VAL2 ++ str r1, [r0] ++ nop ++ nop ++ nop ++ nop ++reset_cpu_loop: ++ b reset_cpu_loop ++ ++WDT_TGCR: ++ .word 0x01c21c24 ++WDT_TIM12: ++ .word 0x01c21c10 ++WDT_TIM34: ++ .word 0x01c21c14 ++WDT_PRD12: ++ .word 0x01c21c18 ++WDT_PRD34: ++ .word 0x01c21c1c ++WDT_TCR: ++ .word 0x01c21c20 ++WDT_WDTCR: ++ .word 0x01c21c28 ++WDTCR_VAL1: ++ .word 0xa5c64000 ++WDTCR_VAL2: ++ .word 0xda7e4000 +Index: u-boot-2009.01/cpu/arm926ejs/da8xx/timer.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/cpu/arm926ejs/da8xx/timer.c +@@ -0,0 +1,148 @@ ++/* ++ * (C) Copyright 2003 ++ * Texas Instruments <www.ti.com> ++ * ++ * (C) Copyright 2002 ++ * Sysgo Real-Time Solutions, GmbH <www.elinos.com> ++ * Marius Groeger <mgroeger@sysgo.de> ++ * ++ * (C) Copyright 2002 ++ * Sysgo Real-Time Solutions, GmbH <www.elinos.com> ++ * Alex Zuepke <azu@sysgo.de> ++ * ++ * (C) Copyright 2002-2004 ++ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> ++ * ++ * (C) Copyright 2004 ++ * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> ++ * ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * 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 <arm926ejs.h> ++ ++typedef volatile struct { ++ u_int32_t pid12; ++ u_int32_t emumgt; ++ u_int32_t na1; ++ u_int32_t na2; ++ u_int32_t tim12; ++ u_int32_t tim34; ++ u_int32_t prd12; ++ u_int32_t prd34; ++ u_int32_t tcr; ++ u_int32_t tgcr; ++ u_int32_t wdtcr; ++} davinci_timer; ++ ++davinci_timer *timer = (davinci_timer *)CONFIG_SYS_TIMERBASE; ++ ++#define TIMER_LOAD_VAL (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ) ++#define TIM_CLK_DIV 16 ++ ++static ulong timestamp; ++static ulong lastinc; ++ ++int timer_init(void) ++{ ++ /* We are using timer34 in unchained 32-bit mode, full speed */ ++ timer->tcr = 0x0; ++ timer->tgcr = 0x0; ++ timer->tgcr = 0x06 | ((TIM_CLK_DIV - 1) << 8); ++ timer->tim34 = 0x0; ++ timer->prd34 = TIMER_LOAD_VAL; ++ lastinc = 0; ++ timestamp = 0; ++ timer->tcr = 2 << 22; ++ ++ return(0); ++} ++ ++void reset_timer(void) ++{ ++ timer->tcr = 0x0; ++ timer->tim34 = 0; ++ lastinc = 0; ++ timestamp = 0; ++ timer->tcr = 2 << 22; ++} ++ ++static ulong get_timer_raw(void) ++{ ++ ulong now = timer->tim34; ++ ++ if (now >= lastinc) { ++ /* normal mode */ ++ timestamp += now - lastinc; ++ } else { ++ /* overflow ... */ ++ timestamp += now + TIMER_LOAD_VAL - lastinc; ++ } ++ lastinc = now; ++ return timestamp; ++} ++ ++ulong get_timer(ulong base) ++{ ++ return((get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base); ++} ++ ++void set_timer(ulong t) ++{ ++ timestamp = t; ++} ++ ++void udelay(unsigned long usec) ++{ ++ ulong tmo; ++ ulong endtime; ++ signed long diff; ++ ++ tmo = CONFIG_SYS_HZ_CLOCK / 1000; ++ tmo *= usec; ++ tmo /= (1000 * TIM_CLK_DIV); ++ ++ endtime = get_timer_raw() + tmo; ++ ++ do { ++ ulong now = get_timer_raw(); ++ diff = endtime - now; ++ } while (diff >= 0); ++} ++ ++/* ++ * This function is derived from PowerPC code (read timebase as long long). ++ * On ARM it just returns the timer value. ++ */ ++unsigned long long get_ticks(void) ++{ ++ return(get_timer(0)); ++} ++ ++/* ++ * This function is derived from PowerPC code (timebase clock frequency). ++ * On ARM it returns the number of timer ticks per second. ++ */ ++ulong get_tbclk(void) ++{ ++ return CONFIG_SYS_HZ; ++} +Index: u-boot-2009.01/include/asm-arm/arch-da8xx/emac_defs.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01/include/asm-arm/arch-da8xx/emac_defs.h +@@ -0,0 +1,331 @@ ++/* ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Based on: ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * dm644x_emac.h ++ * ++ * TI DaVinci (DM644X) EMAC peripheral driver header for DV-EVM ++ * ++ * Copyright (C) 2005 Texas Instruments. ++ * ++ * ---------------------------------------------------------------------------- ++ * ++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ---------------------------------------------------------------------------- ++ ++ * Modifications: ++ * ver. 1.0: Sep 2005, TI PSP Team - Created EMAC version for uBoot. ++ * ++ */ ++ ++#ifndef _DM644X_EMAC_H_ ++#define _DM644X_EMAC_H_ ++ ++#include <asm/arch/hardware.h> ++ ++#define EMAC_BASE_ADDR DAVINCI_EMAC_CNTRL_REGS_BASE ++#define EMAC_WRAPPER_BASE_ADDR DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE ++#define EMAC_WRAPPER_RAM_ADDR DAVINCI_EMAC_WRAPPER_RAM_BASE ++#define EMAC_MDIO_BASE_ADDR DAVINCI_MDIO_CNTRL_REGS_BASE ++ ++/* MDIO module input frequency */ ++#define EMAC_MDIO_BUS_FREQ clk_get(DAVINCI_MDIO_CLKID) ++ ++/* MDIO clock output frequency */ ++#define EMAC_MDIO_CLOCK_FREQ 2000000 /* 2.0 MHz */ ++ ++/* Ethernet Min/Max packet size */ ++#define EMAC_MIN_ETHERNET_PKT_SIZE 60 ++#define EMAC_MAX_ETHERNET_PKT_SIZE 1518 ++#define EMAC_PKT_ALIGN 18 /* 1518 + 18 = 1536 (packet aligned on 32 byte boundry) */ ++ ++/* Number of RX packet buffers ++ * NOTE: Only 1 buffer supported as of now ++ */ ++#define EMAC_MAX_RX_BUFFERS 10 ++ ++ ++/*********************************************** ++ ******** Internally used macros *************** ++ ***********************************************/ ++ ++#define EMAC_CH_TX 1 ++#define EMAC_CH_RX 0 ++ ++/* Each descriptor occupies 4 words, lets start RX desc's at 0 and ++ * reserve space for 64 descriptors max ++ */ ++#define EMAC_RX_DESC_BASE 0x0 ++#define EMAC_TX_DESC_BASE 0x1000 ++ ++/* EMAC Teardown value */ ++#define EMAC_TEARDOWN_VALUE 0xfffffffc ++ ++/* MII Status Register */ ++#define MII_STATUS_REG 1 ++ ++/* Number of statistics registers */ ++#define EMAC_NUM_STATS 36 ++ ++ ++/* EMAC Descriptor */ ++typedef volatile struct _emac_desc ++{ ++ u_int32_t next; /* Pointer to next descriptor in chain */ ++ u_int8_t *buffer; /* Pointer to data buffer */ ++ u_int32_t buff_off_len; /* Buffer Offset(MSW) and Length(LSW) */ ++ u_int32_t pkt_flag_len; /* Packet Flags(MSW) and Length(LSW) */ ++} emac_desc; ++ ++/* CPPI bit positions */ ++#define EMAC_CPPI_SOP_BIT (0x80000000) ++#define EMAC_CPPI_EOP_BIT (0x40000000) ++#define EMAC_CPPI_OWNERSHIP_BIT (0x20000000) ++#define EMAC_CPPI_EOQ_BIT (0x10000000) ++#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT (0x08000000) ++#define EMAC_CPPI_PASS_CRC_BIT (0x04000000) ++ ++#define EMAC_CPPI_RX_ERROR_FRAME (0x03fc0000) ++ ++#define EMAC_MACCONTROL_RMIISPEED_100 (1 << 15) ++#define EMAC_MACCONTROL_MIIEN_ENABLE (0x20) ++#define EMAC_MACCONTROL_FULLDUPLEX_ENABLE (0x1) ++ ++#define EMAC_RXMBPENABLE_RXCAFEN_ENABLE (0x200000) ++#define EMAC_RXMBPENABLE_RXBROADEN (0x2000) ++ ++ ++#define MDIO_CONTROL_IDLE (0x80000000) ++#define MDIO_CONTROL_ENABLE (0x40000000) ++#define MDIO_CONTROL_FAULT_ENABLE (0x40000) ++#define MDIO_CONTROL_FAULT (0x80000) ++#define MDIO_USERACCESS0_GO (0x80000000) ++#define MDIO_USERACCESS0_WRITE_READ (0x0) ++#define MDIO_USERACCESS0_WRITE_WRITE (0x40000000) ++#define MDIO_USERACCESS0_ACK (0x20000000) ++ ++/* Ethernet MAC Registers Structure */ ++typedef struct { ++ dv_reg TXIDVER; ++ dv_reg TXCONTROL; ++ dv_reg TXTEARDOWN; ++ u_int8_t RSVD0[4]; ++ dv_reg RXIDVER; ++ dv_reg RXCONTROL; ++ dv_reg RXTEARDOWN; ++ u_int8_t RSVD1[100]; ++ dv_reg TXINTSTATRAW; ++ dv_reg TXINTSTATMASKED; ++ dv_reg TXINTMASKSET; ++ dv_reg TXINTMASKCLEAR; ++ dv_reg MACINVECTOR; ++ u_int8_t RSVD2[12]; ++ dv_reg RXINTSTATRAW; ++ dv_reg RXINTSTATMASKED; ++ dv_reg RXINTMASKSET; ++ dv_reg RXINTMASKCLEAR; ++ dv_reg MACINTSTATRAW; ++ dv_reg MACINTSTATMASKED; ++ dv_reg MACINTMASKSET; ++ dv_reg MACINTMASKCLEAR; ++ u_int8_t RSVD3[64]; ++ dv_reg RXMBPENABLE; ++ dv_reg RXUNICASTSET; ++ dv_reg RXUNICASTCLEAR; ++ dv_reg RXMAXLEN; ++ dv_reg RXBUFFEROFFSET; ++ dv_reg RXFILTERLOWTHRESH; ++ u_int8_t RSVD4[8]; ++ dv_reg RX0FLOWTHRESH; ++ dv_reg RX1FLOWTHRESH; ++ dv_reg RX2FLOWTHRESH; ++ dv_reg RX3FLOWTHRESH; ++ dv_reg RX4FLOWTHRESH; ++ dv_reg RX5FLOWTHRESH; ++ dv_reg RX6FLOWTHRESH; ++ dv_reg RX7FLOWTHRESH; ++ dv_reg RX0FREEBUFFER; ++ dv_reg RX1FREEBUFFER; ++ dv_reg RX2FREEBUFFER; ++ dv_reg RX3FREEBUFFER; ++ dv_reg RX4FREEBUFFER; ++ dv_reg RX5FREEBUFFER; ++ dv_reg RX6FREEBUFFER; ++ dv_reg RX7FREEBUFFER; ++ dv_reg MACCONTROL; ++ dv_reg MACSTATUS; ++ dv_reg EMCONTROL; ++ dv_reg FIFOCONTROL; ++ dv_reg MACCONFIG; ++ dv_reg SOFTRESET; ++ u_int8_t RSVD5[88]; ++ dv_reg MACSRCADDRLO; ++ dv_reg MACSRCADDRHI; ++ dv_reg MACHASH1; ++ dv_reg MACHASH2; ++ dv_reg BOFFTEST; ++ dv_reg TPACETEST; ++ dv_reg RXPAUSE; ++ dv_reg TXPAUSE; ++ u_int8_t RSVD6[16]; ++ dv_reg RXGOODFRAMES; ++ dv_reg RXBCASTFRAMES; ++ dv_reg RXMCASTFRAMES; ++ dv_reg RXPAUSEFRAMES; ++ dv_reg RXCRCERRORS; ++ dv_reg RXALIGNCODEERRORS; ++ dv_reg RXOVERSIZED; ++ dv_reg RXJABBER; ++ dv_reg RXUNDERSIZED; ++ dv_reg RXFRAGMENTS; ++ dv_reg RXFILTERED; ++ dv_reg RXQOSFILTERED; ++ dv_reg RXOCTETS; ++ dv_reg TXGOODFRAMES; ++ dv_reg TXBCASTFRAMES; ++ dv_reg TXMCASTFRAMES; ++ dv_reg TXPAUSEFRAMES; ++ dv_reg TXDEFERRED; ++ dv_reg TXCOLLISION; ++ dv_reg TXSINGLECOLL; ++ dv_reg TXMULTICOLL; ++ dv_reg TXEXCESSIVECOLL; ++ dv_reg TXLATECOLL; ++ dv_reg TXUNDERRUN; ++ dv_reg TXCARRIERSENSE; ++ dv_reg TXOCTETS; ++ dv_reg FRAME64; ++ dv_reg FRAME65T127; ++ dv_reg FRAME128T255; ++ dv_reg FRAME256T511; ++ dv_reg FRAME512T1023; ++ dv_reg FRAME1024TUP; ++ dv_reg NETOCTETS; ++ dv_reg RXSOFOVERRUNS; ++ dv_reg RXMOFOVERRUNS; ++ dv_reg RXDMAOVERRUNS; ++ u_int8_t RSVD7[624]; ++ dv_reg MACADDRLO; ++ dv_reg MACADDRHI; ++ dv_reg MACINDEX; ++ u_int8_t RSVD8[244]; ++ dv_reg TX0HDP; ++ dv_reg TX1HDP; ++ dv_reg TX2HDP; ++ dv_reg TX3HDP; ++ dv_reg TX4HDP; ++ dv_reg TX5HDP; ++ dv_reg TX6HDP; ++ dv_reg TX7HDP; ++ dv_reg RX0HDP; ++ dv_reg RX1HDP; ++ dv_reg RX2HDP; ++ dv_reg RX3HDP; ++ dv_reg RX4HDP; ++ dv_reg RX5HDP; ++ dv_reg RX6HDP; ++ dv_reg RX7HDP; ++ dv_reg TX0CP; ++ dv_reg TX1CP; ++ dv_reg TX2CP; ++ dv_reg TX3CP; ++ dv_reg TX4CP; ++ dv_reg TX5CP; ++ dv_reg TX6CP; ++ dv_reg TX7CP; ++ dv_reg RX0CP; ++ dv_reg RX1CP; ++ dv_reg RX2CP; ++ dv_reg RX3CP; ++ dv_reg RX4CP; ++ dv_reg RX5CP; ++ dv_reg RX6CP; ++ dv_reg RX7CP; ++} emac_regs; ++ ++/* EMAC Wrapper Registers Structure */ ++typedef struct { ++ dv_reg REV; ++ dv_reg SOFTRESET; ++ dv_reg INTCONTROL; ++ dv_reg C0RXTHRESHEN; ++ dv_reg C0RXEN; ++ dv_reg C0TXEN; ++ dv_reg C0MISCEN; ++ dv_reg C1RXTHRESHEN; ++ dv_reg C1RXEN; ++ dv_reg C1TXEN; ++ dv_reg C1MISCEN; ++ dv_reg C2RXTHRESHEN; ++ dv_reg C2RXEN; ++ dv_reg C2TXEN; ++ dv_reg C2MISCEN; ++ dv_reg C0RXTHRESHSTAT; ++ dv_reg C0RXSTAT; ++ dv_reg C0TXSTAT; ++ dv_reg C0MISCSTAT; ++ dv_reg C1RXTHRESHSTAT; ++ dv_reg C1RXSTAT; ++ dv_reg C1TXSTAT; ++ dv_reg C1MISCSTAT; ++ dv_reg C2RXTHRESHSTAT; ++ dv_reg C2RXSTAT; ++ dv_reg C2TXSTAT; ++ dv_reg C2MISCSTAT; ++ dv_reg C0RXIMAX; ++ dv_reg C0TXIMAX; ++ dv_reg C1RXIMAX; ++ dv_reg C1TXIMAX; ++ dv_reg C2RXIMAX; ++ dv_reg C2TXIMAX; ++} ewrap_regs; ++ ++ ++/* EMAC MDIO Registers Structure */ ++typedef struct { ++ dv_reg VERSION; ++ dv_reg CONTROL; ++ dv_reg ALIVE; ++ dv_reg LINK; ++ dv_reg LINKINTRAW; ++ dv_reg LINKINTMASKED; ++ u_int8_t RSVD0[8]; ++ dv_reg USERINTRAW; ++ dv_reg USERINTMASKED; ++ dv_reg USERINTMASKSET; ++ dv_reg USERINTMASKCLEAR; ++ u_int8_t RSVD1[80]; ++ dv_reg USERACCESS0; ++ dv_reg USERPHYSEL0; ++ dv_reg USERACCESS1; ++ dv_reg USERPHYSEL1; ++} mdio_regs; ++ ++int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data); ++int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data); ++ ++typedef struct ++{ ++ char name[64]; ++ int (*init)(int phy_addr); ++ int (*is_phy_connected)(int phy_addr); ++ int (*get_link_speed)(int phy_addr); ++ int (*auto_negotiate)(int phy_addr); ++} phy_t; ++ ++#endif /* _DM644X_EMAC_H_ */ +Index: u-boot-2009.01/include/asm-arm/arch-da8xx/emif_defs.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01/include/asm-arm/arch-da8xx/emif_defs.h +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * 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 ++ */ ++#ifndef _EMIF_DEFS_H_ ++#define _EMIF_DEFS_H_ ++ ++#include <asm/arch/hardware.h> ++ ++typedef struct { ++ dv_reg ERCSR; ++ dv_reg AWCCR; ++ dv_reg SDBCR; ++ dv_reg SDRCR; ++ dv_reg AB1CR; ++ dv_reg AB2CR; ++ dv_reg AB3CR; ++ dv_reg AB4CR; ++ dv_reg SDTIMR; ++ dv_reg DDRSR; ++ dv_reg DDRPHYCR; ++ dv_reg DDRPHYSR; ++ dv_reg TOTAR; ++ dv_reg TOTACTR; ++ dv_reg DDRPHYID_REV; ++ dv_reg SDSRETR; ++ dv_reg EIRR; ++ dv_reg EIMR; ++ dv_reg EIMSR; ++ dv_reg EIMCR; ++ dv_reg IOCTRLR; ++ dv_reg IOSTATR; ++ u_int8_t RSVD0[8]; ++ dv_reg NANDFCR; ++ dv_reg NANDFSR; ++ u_int8_t RSVD1[8]; ++ dv_reg NANDF1ECC; ++ dv_reg NANDF2ECC; ++ dv_reg NANDF3ECC; ++ dv_reg NANDF4ECC; ++} emif_registers; ++ ++typedef emif_registers *emifregs; ++#endif +Index: u-boot-2009.01/include/asm-arm/arch-da8xx/hardware.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01/include/asm-arm/arch-da8xx/hardware.h +@@ -0,0 +1,199 @@ ++/* ++ * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc ++ * ++ * Based on hardware.h for DaVinci. Original Copyrights follow. ++ * ++ * Sergey Kubushyn <ksi@koi8.net> ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Based on: ++ * ++ * ------------------------------------------------------------------------- ++ * ++ * linux/include/asm-arm/arch-davinci/hardware.h ++ * ++ * Copyright (C) 2006 Texas Instruments. ++ * ++ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * 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., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++#ifndef __ASM_ARCH_HARDWARE_H ++#define __ASM_ARCH_HARDWARE_H ++ ++#include <config.h> ++ ++#ifndef __ASSEMBLY__ ++ ++#include <asm/sizes.h> ++ ++#define REG(addr) (*(volatile unsigned int *)(addr)) ++#define REG_P(addr) ((volatile unsigned int *)(addr)) ++ ++typedef volatile unsigned int dv_reg; ++typedef volatile unsigned int * dv_reg_p; ++ ++#endif ++ ++/* ++ * Base register addresses ++ */ ++#define DAVINCI_UART0_BASE (0x01c42000) ++#define DAVINCI_UART1_BASE (0x01d0c000) ++#define DAVINCI_UART2_BASE (0x01d0d000) ++#define DAVINCI_I2C0_BASE (0x01c22000) ++#define DAVINCI_I2C1_BASE (0x01e28000) ++#define DAVINCI_TIMER0_BASE (0x01c20000) ++#define DAVINCI_TIMER1_BASE (0x01c21000) ++#define DAVINCI_WDOG_BASE (0x01c21000) ++#define DAVINCI_PLL_CNTRL0_BASE (0x01c11000) ++#define DAVINCI_PSC0_BASE (0x01c10000) ++#define DAVINCI_PSC1_BASE (0x01e27000) ++#define DAVINCI_SPI0_BASE (0x01c41000) ++#define DAVINCI_SPI1_BASE (0x01e12000) ++#define DAVINCI_GPIO_BASE (0x01e26000) ++#define DAVINCI_EMAC_CNTRL_REGS_BASE (0x01e23000) ++#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE (0x01e22000) ++#define DAVINCI_EMAC_WRAPPER_RAM_BASE (0x01e20000) ++#define DAVINCI_MDIO_CNTRL_REGS_BASE (0x01e24000) ++#define DAVINCI_ASYNC_EMIF_CNTRL_BASE (0x68000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE (0x40000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE (0x60000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE (0x62000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE4_BASE (0x64000000) ++#define DAVINCI_ASYNC_EMIF_DATA_CE5_BASE (0x66000000) ++#define DAVINCI_DDR_EMIF_CTRL_BASE (0xb0000000) ++#define DAVINCI_DDR_EMIF_DATA_BASE (0xc0000000) ++#define DAVINCI_INTC_BASE (0xfffee000) ++#define DAVINCI_BOOTCFG_BASE (0x01c14000) ++ ++/* Clock IDs */ ++#define DAVINCI_PLLM_CLKID (0xFF + 0) ++#define DAVINCI_PLLC_CLKID (0xFF + 1) ++#define DAVINCI_AUXCLK_CLKID (0xFF + 2) ++#define DAVINCI_MDIO_CLKID 4 ++#define DAVINCI_SPI0_CLKID 2 ++#define DAVINCI_UART2_CLKID 2 ++#define DAVINCI_ARM_CLKID 6 ++ ++/* Power and Sleep Controller (PSC) Domains */ ++#define DAVINCI_GPSC_ARMDOMAIN 0 ++#define DAVINCI_GPSC_DSPDOMAIN 1 ++ ++/* LPSCs in PSC0 */ ++#define DAVINCI_LPSC_TPCC 0 ++#define DAVINCI_LPSC_TPTC0 1 ++#define DAVINCI_LPSC_TPTC1 2 ++#define DAVINCI_LPSC_AEMIF 3 ++#define DAVINCI_LPSC_SPI0 4 ++#define DAVINCI_LPSC_MMC_SD 5 ++#define DAVINCI_LPSC_AINTC 6 ++#define DAVINCI_LPSC_ARM_RAM_ROM 7 ++#define DAVINCI_LPSC_SECCTL_KEYMGR 8 ++#define DAVINCI_LPSC_UART0 9 ++#define DAVINCI_LPSC_SCR0 10 ++#define DAVINCI_LPSC_SCR1 11 ++#define DAVINCI_LPSC_SCR2 12 ++#define DAVINCI_LPSC_DMAX 13 ++#define DAVINCI_LPSC_ARM 14 ++#define DAVINCI_LPSC_GEM 15 ++ ++/* for LPSCs in PSC1, 32 + actual id is being used for differentiation */ ++#define DAVINCI_LPSC_USB11 (32 + 1) ++#define DAVINCI_LPSC_USB20 (32 + 2) ++#define DAVINCI_LPSC_GPIO (32 + 3) ++#define DAVINCI_LPSC_UHPI (32 + 4) ++#define DAVINCI_LPSC_EMAC (32 + 5) ++#define DAVINCI_LPSC_DDR_EMIF (32 + 6) ++#define DAVINCI_LPSC_McASP0 (32 + 7) ++#define DAVINCI_LPSC_McASP1 (32 + 8) ++#define DAVINCI_LPSC_McASP2 (32 + 9) ++#define DAVINCI_LPSC_SPI1 (32 + 10) ++#define DAVINCI_LPSC_I2C1 (32 + 11) ++#define DAVINCI_LPSC_UART1 (32 + 12) ++#define DAVINCI_LPSC_UART2 (32 + 13) ++#define DAVINCI_LPSC_LCDC (32 + 16) ++#define DAVINCI_LPSC_ePWM (32 + 17) ++#define DAVINCI_LPSC_eCAP (32 + 20) ++#define DAVINCI_LPSC_eQEP (32 + 21) ++#define DAVINCI_LPSC_SCR_P0 (32 + 22) ++#define DAVINCI_LPSC_SCR_P1 (32 + 23) ++#define DAVINCI_LPSC_CR_P3 (32 + 26) ++#define DAVINCI_LPSC_L3_CBA_RAM (32 + 31) ++ ++/* Some PSC defines */ ++ ++#define PSC0_MDCTL (DAVINCI_PSC0_BASE + 0xa00) ++#define PSC0_MDSTAT (DAVINCI_PSC0_BASE + 0x800) ++#define PSC0_PTCMD (DAVINCI_PSC0_BASE + 0x120) ++#define PSC0_PTSTAT (DAVINCI_PSC0_BASE + 0x128) ++ ++#define PSC1_MDCTL (DAVINCI_PSC1_BASE + 0xa00) ++#define PSC1_MDSTAT (DAVINCI_PSC1_BASE + 0x800) ++#define PSC1_PTCMD (DAVINCI_PSC1_BASE + 0x120) ++#define PSC1_PTSTAT (DAVINCI_PSC1_BASE + 0x128) ++ ++/* Some PLL defines */ ++#define PLL0_PLLCTL (DAVINCI_PLL_CNTRL0_BASE + 0x100) ++#define PLL0_PLLM (DAVINCI_PLL_CNTRL0_BASE + 0x110) ++#define PLL0_PREDIV (DAVINCI_PLL_CNTRL0_BASE + 0x114) ++#define PLL0_POSTDIV (DAVINCI_PLL_CNTRL0_BASE + 0x128) ++#define PLL0_DIV1 (DAVINCI_PLL_CNTRL0_BASE + 0x118) ++#define PLL0_DIV2 (DAVINCI_PLL_CNTRL0_BASE + 0x11c) ++#define PLL0_DIV3 (DAVINCI_PLL_CNTRL0_BASE + 0x120) ++#define PLL0_DIV4 (DAVINCI_PLL_CNTRL0_BASE + 0x160) ++#define PLL0_DIV5 (DAVINCI_PLL_CNTRL0_BASE + 0x164) ++#define PLL0_DIV6 (DAVINCI_PLL_CNTRL0_BASE + 0x168) ++#define PLL0_DIV7 (DAVINCI_PLL_CNTRL0_BASE + 0x16c) ++#define PLL0_DIV8 (DAVINCI_PLL_CNTRL0_BASE + 0x170) ++#define PLL0_DIV9 (DAVINCI_PLL_CNTRL0_BASE + 0x114) ++ ++/* Boot config */ ++#define KICK0 (DAVINCI_BOOTCFG_BASE + 0x38) ++#define KICK1 (DAVINCI_BOOTCFG_BASE + 0x3c) ++#define PINMUX0 (DAVINCI_BOOTCFG_BASE + 0x120) ++#define PINMUX1 (DAVINCI_BOOTCFG_BASE + 0x124) ++#define PINMUX2 (DAVINCI_BOOTCFG_BASE + 0x128) ++#define PINMUX3 (DAVINCI_BOOTCFG_BASE + 0x12c) ++#define PINMUX4 (DAVINCI_BOOTCFG_BASE + 0x130) ++#define PINMUX5 (DAVINCI_BOOTCFG_BASE + 0x134) ++#define PINMUX6 (DAVINCI_BOOTCFG_BASE + 0x138) ++#define PINMUX7 (DAVINCI_BOOTCFG_BASE + 0x13c) ++#define PINMUX8 (DAVINCI_BOOTCFG_BASE + 0x140) ++#define PINMUX9 (DAVINCI_BOOTCFG_BASE + 0x144) ++#define PINMUX10 (DAVINCI_BOOTCFG_BASE + 0x148) ++#define PINMUX11 (DAVINCI_BOOTCFG_BASE + 0x14c) ++#define PINMUX12 (DAVINCI_BOOTCFG_BASE + 0x150) ++#define PINMUX13 (DAVINCI_BOOTCFG_BASE + 0x154) ++#define PINMUX14 (DAVINCI_BOOTCFG_BASE + 0x158) ++#define PINMUX15 (DAVINCI_BOOTCFG_BASE + 0x15C) ++#define PINMUX16 (DAVINCI_BOOTCFG_BASE + 0x160) ++#define PINMUX17 (DAVINCI_BOOTCFG_BASE + 0x164) ++#define PINMUX18 (DAVINCI_BOOTCFG_BASE + 0x168) ++#define PINMUX19 (DAVINCI_BOOTCFG_BASE + 0x16c) ++#define SUSPSRC (DAVINCI_BOOTCFG_BASE + 0x170) ++#define CFGCHIP0 (DAVINCI_BOOTCFG_BASE + 0x17c) ++ ++/* Interrupt controller */ ++#define INTC_GLB_EN (DAVINCI_INTC_BASE + 0x10) ++#define INTC_HINT_EN (DAVINCI_INTC_BASE + 0x1500) ++#define INTC_EN_CLR0 (DAVINCI_INTC_BASE + 0x380) ++ ++#endif /* __ASM_ARCH_HARDWARE_H */ +Index: u-boot-2009.01/include/asm-arm/arch-da8xx/i2c_defs.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01/include/asm-arm/arch-da8xx/i2c_defs.h +@@ -0,0 +1,95 @@ ++/* ++ * (C) Copyright 2004 ++ * Texas Instruments, <www.ti.com> ++ * ++ * Some changes copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * 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 ++ */ ++#ifndef _DAVINCI_I2C_H_ ++#define _DAVINCI_I2C_H_ ++ ++#define I2C_WRITE 0 ++#define I2C_READ 1 ++ ++#define I2C_BASE 0x01c22000 ++ ++#define I2C_OA (I2C_BASE + 0x00) ++#define I2C_IE (I2C_BASE + 0x04) ++#define I2C_STAT (I2C_BASE + 0x08) ++#define I2C_SCLL (I2C_BASE + 0x0c) ++#define I2C_SCLH (I2C_BASE + 0x10) ++#define I2C_CNT (I2C_BASE + 0x14) ++#define I2C_DRR (I2C_BASE + 0x18) ++#define I2C_SA (I2C_BASE + 0x1c) ++#define I2C_DXR (I2C_BASE + 0x20) ++#define I2C_CON (I2C_BASE + 0x24) ++#define I2C_IV (I2C_BASE + 0x28) ++#define I2C_PSC (I2C_BASE + 0x30) ++ ++/* I2C masks */ ++ ++/* I2C Interrupt Enable Register (I2C_IE): */ ++#define I2C_IE_SCD_IE (1 << 5) /* Stop condition detect interrupt enable */ ++#define I2C_IE_XRDY_IE (1 << 4) /* Transmit data ready interrupt enable */ ++#define I2C_IE_RRDY_IE (1 << 3) /* Receive data ready interrupt enable */ ++#define I2C_IE_ARDY_IE (1 << 2) /* Register access ready interrupt enable */ ++#define I2C_IE_NACK_IE (1 << 1) /* No acknowledgment interrupt enable */ ++#define I2C_IE_AL_IE (1 << 0) /* Arbitration lost interrupt enable */ ++ ++/* I2C Status Register (I2C_STAT): */ ++ ++#define I2C_STAT_BB (1 << 12) /* Bus busy */ ++#define I2C_STAT_ROVR (1 << 11) /* Receive overrun */ ++#define I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ ++#define I2C_STAT_AAS (1 << 9) /* Address as slave */ ++#define I2C_STAT_SCD (1 << 5) /* Stop condition detect */ ++#define I2C_STAT_XRDY (1 << 4) /* Transmit data ready */ ++#define I2C_STAT_RRDY (1 << 3) /* Receive data ready */ ++#define I2C_STAT_ARDY (1 << 2) /* Register access ready */ ++#define I2C_STAT_NACK (1 << 1) /* No acknowledgment interrupt enable */ ++#define I2C_STAT_AL (1 << 0) /* Arbitration lost interrupt enable */ ++ ++ ++/* I2C Interrupt Code Register (I2C_INTCODE): */ ++ ++#define I2C_INTCODE_MASK 7 ++#define I2C_INTCODE_NONE 0 ++#define I2C_INTCODE_AL 1 /* Arbitration lost */ ++#define I2C_INTCODE_NAK 2 /* No acknowledgement/general call */ ++#define I2C_INTCODE_ARDY 3 /* Register access ready */ ++#define I2C_INTCODE_RRDY 4 /* Rcv data ready */ ++#define I2C_INTCODE_XRDY 5 /* Xmit data ready */ ++#define I2C_INTCODE_SCD 6 /* Stop condition detect */ ++ ++ ++/* I2C Configuration Register (I2C_CON): */ ++ ++#define I2C_CON_EN (1 << 5) /* I2C module enable */ ++#define I2C_CON_STB (1 << 4) /* Start byte mode (master mode only) */ ++#define I2C_CON_MST (1 << 10) /* Master/slave mode */ ++#define I2C_CON_TRX (1 << 9) /* Transmitter/receiver mode (master mode only) */ ++#define I2C_CON_XA (1 << 8) /* Expand address */ ++#define I2C_CON_STP (1 << 11) /* Stop condition (master mode only) */ ++#define I2C_CON_STT (1 << 13) /* Start condition (master mode only) */ ++#define I2C_CON_FREE (1 << 14) /* Free run on emulation */ ++ ++#define I2C_TIMEOUT 0xffff0000 /* Timeout mask for poll_i2c_irq() */ ++ ++#endif +Index: u-boot-2009.01/include/asm-arm/arch-da8xx/nand_defs.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01/include/asm-arm/arch-da8xx/nand_defs.h +@@ -0,0 +1,164 @@ ++/* ++ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> ++ * ++ * Parts shamelesly stolen from Linux Kernel source tree. ++ * ++ * ------------------------------------------------------------ ++ * ++ * 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 ++ */ ++#ifndef _NAND_DEFS_H_ ++#define _NAND_DEFS_H_ ++ ++#include <asm/arch/hardware.h> ++ ++#define MASK_CLE 0x10 ++//#define MASK_ALE 0x0a ++#define MASK_ALE 0x08 ++ ++ ++#define NAND_CE0CLE ((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x10)) ++//#define NAND_CE0ALE ((volatile u_int8_t *)(CFG_NAND_BASE + 0x0a)) ++#define NAND_CE0ALE ((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x08)) ++#define NAND_CE0DATA ((volatile u_int8_t *)CONFIG_SYS_NAND_BASE) ++ ++typedef struct { ++ u_int32_t NRCSR; ++ u_int32_t AWCCR; ++ u_int8_t RSVD0[8]; ++ u_int32_t AB1CR; ++ u_int32_t AB2CR; ++ u_int32_t AB3CR; ++ u_int32_t AB4CR; ++ u_int8_t RSVD1[32]; ++ u_int32_t NIRR; ++ u_int32_t NIMR; ++ u_int32_t NIMSR; ++ u_int32_t NIMCR; ++ u_int8_t RSVD2[16]; ++ u_int32_t NANDFCR; ++ u_int32_t NANDFSR; ++ u_int8_t RSVD3[8]; ++ u_int32_t NANDF1ECC; ++ u_int32_t NANDF2ECC; ++ u_int32_t NANDF3ECC; ++ u_int32_t NANDF4ECC; ++ u_int8_t RSVD4[4]; ++ u_int32_t IODFTECR; ++ u_int32_t IODFTGCR; ++ u_int8_t RSVD5[4]; ++ u_int32_t IODFTMRLR; ++ u_int32_t IODFTMRMR; ++ u_int32_t IODFTMRMSBR; ++ u_int8_t RSVD6[20]; ++ u_int32_t MODRNR; ++ u_int8_t RSVD7[76]; ++ u_int32_t CE0DATA; ++ u_int32_t CE0ALE; ++ u_int32_t CE0CLE; ++ u_int8_t RSVD8[4]; ++ u_int32_t CE1DATA; ++ u_int32_t CE1ALE; ++ u_int32_t CE1CLE; ++ u_int8_t RSVD9[4]; ++ u_int32_t CE2DATA; ++ u_int32_t CE2ALE; ++ u_int32_t CE2CLE; ++ u_int8_t RSVD10[4]; ++ u_int32_t CE3DATA; ++ u_int32_t CE3ALE; ++ u_int32_t CE3CLE; ++} nand_registers; ++ ++typedef volatile nand_registers *nandregs; ++ ++#define NAND_READ_START 0x00 ++#define NAND_READ_END 0x30 ++#define NAND_STATUS 0x70 ++ ++#ifdef CFG_NAND_HW_ECC ++#define NAND_Ecc_P1e (1 << 0) ++#define NAND_Ecc_P2e (1 << 1) ++#define NAND_Ecc_P4e (1 << 2) ++#define NAND_Ecc_P8e (1 << 3) ++#define NAND_Ecc_P16e (1 << 4) ++#define NAND_Ecc_P32e (1 << 5) ++#define NAND_Ecc_P64e (1 << 6) ++#define NAND_Ecc_P128e (1 << 7) ++#define NAND_Ecc_P256e (1 << 8) ++#define NAND_Ecc_P512e (1 << 9) ++#define NAND_Ecc_P1024e (1 << 10) ++#define NAND_Ecc_P2048e (1 << 11) ++ ++#define NAND_Ecc_P1o (1 << 16) ++#define NAND_Ecc_P2o (1 << 17) ++#define NAND_Ecc_P4o (1 << 18) ++#define NAND_Ecc_P8o (1 << 19) ++#define NAND_Ecc_P16o (1 << 20) ++#define NAND_Ecc_P32o (1 << 21) ++#define NAND_Ecc_P64o (1 << 22) ++#define NAND_Ecc_P128o (1 << 23) ++#define NAND_Ecc_P256o (1 << 24) ++#define NAND_Ecc_P512o (1 << 25) ++#define NAND_Ecc_P1024o (1 << 26) ++#define NAND_Ecc_P2048o (1 << 27) ++ ++#define TF(v) (v ? 1 : 0) ++ ++#define P2048e(a) (TF(a & NAND_Ecc_P2048e) << 0) ++#define P2048o(a) (TF(a & NAND_Ecc_P2048o) << 1) ++#define P1e(a) (TF(a & NAND_Ecc_P1e) << 2) ++#define P1o(a) (TF(a & NAND_Ecc_P1o) << 3) ++#define P2e(a) (TF(a & NAND_Ecc_P2e) << 4) ++#define P2o(a) (TF(a & NAND_Ecc_P2o) << 5) ++#define P4e(a) (TF(a & NAND_Ecc_P4e) << 6) ++#define P4o(a) (TF(a & NAND_Ecc_P4o) << 7) ++ ++#define P8e(a) (TF(a & NAND_Ecc_P8e) << 0) ++#define P8o(a) (TF(a & NAND_Ecc_P8o) << 1) ++#define P16e(a) (TF(a & NAND_Ecc_P16e) << 2) ++#define P16o(a) (TF(a & NAND_Ecc_P16o) << 3) ++#define P32e(a) (TF(a & NAND_Ecc_P32e) << 4) ++#define P32o(a) (TF(a & NAND_Ecc_P32o) << 5) ++#define P64e(a) (TF(a & NAND_Ecc_P64e) << 6) ++#define P64o(a) (TF(a & NAND_Ecc_P64o) << 7) ++ ++#define P128e(a) (TF(a & NAND_Ecc_P128e) << 0) ++#define P128o(a) (TF(a & NAND_Ecc_P128o) << 1) ++#define P256e(a) (TF(a & NAND_Ecc_P256e) << 2) ++#define P256o(a) (TF(a & NAND_Ecc_P256o) << 3) ++#define P512e(a) (TF(a & NAND_Ecc_P512e) << 4) ++#define P512o(a) (TF(a & NAND_Ecc_P512o) << 5) ++#define P1024e(a) (TF(a & NAND_Ecc_P1024e) << 6) ++#define P1024o(a) (TF(a & NAND_Ecc_P1024o) << 7) ++ ++#define P8e_s(a) (TF(a & NAND_Ecc_P8e) << 0) ++#define P8o_s(a) (TF(a & NAND_Ecc_P8o) << 1) ++#define P16e_s(a) (TF(a & NAND_Ecc_P16e) << 2) ++#define P16o_s(a) (TF(a & NAND_Ecc_P16o) << 3) ++#define P1e_s(a) (TF(a & NAND_Ecc_P1e) << 4) ++#define P1o_s(a) (TF(a & NAND_Ecc_P1o) << 5) ++#define P2e_s(a) (TF(a & NAND_Ecc_P2e) << 6) ++#define P2o_s(a) (TF(a & NAND_Ecc_P2o) << 7) ++ ++#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) ++#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) ++#endif ++ ++#endif +Index: u-boot-2009.01/Makefile +=================================================================== +--- u-boot-2009.01.orig/Makefile ++++ u-boot-2009.01/Makefile +@@ -151,7 +151,8 @@ ifeq ($(ARCH),ppc) + CROSS_COMPILE = ppc_8xx- + endif + ifeq ($(ARCH),arm) +-CROSS_COMPILE = arm-linux- ++#CROSS_COMPILE = arm-linux- ++CROSS_COMPILE = arm-none-linux-gnueabi- + endif + ifeq ($(ARCH),i386) + CROSS_COMPILE = i386-linux- +@@ -2715,6 +2716,9 @@ davinci_sffsdr_config : unconfig + davinci_sonata_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs sonata davinci davinci + ++da8xx_evm_config : unconfig ++ @$(MKCONFIG) $(@:_config=) arm arm926ejs da8xx-evm da8xx da8xx ++ + lpd7a400_config \ + lpd7a404_config: unconfig + @$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x +Index: u-boot-2009.01/lib_arm/board.c +=================================================================== +--- u-boot-2009.01.orig/lib_arm/board.c ++++ u-boot-2009.01/lib_arm/board.c +@@ -416,9 +416,9 @@ void start_armboot (void) + + /* Perform network card initialisation if necessary */ + #ifdef CONFIG_DRIVER_TI_EMAC +-extern void davinci_eth_set_mac_addr (const u_int8_t *addr); ++extern void dm644x_eth_set_mac_addr (const u_int8_t *addr); + if (getenv ("ethaddr")) { +- davinci_eth_set_mac_addr(gd->bd->bi_enetaddr); ++ dm644x_eth_set_mac_addr(gd->bd->bi_enetaddr); + } + #endif + +Index: u-boot-2009.01/drivers/mtd/spi/winbond.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/drivers/mtd/spi/winbond.c +@@ -0,0 +1,338 @@ ++/* ++ * Copyright 2008, Network Appliance Inc. ++ * Author: Jason McMullan <[EMAIL PROTECTED]> ++ * ++ */ ++ ++#include <common.h> ++#include <malloc.h> ++#include <spi_flash.h> ++ ++#include "spi_flash_internal.h" ++ ++/* M25Pxx-specific commands */ ++#define CMD_W25_WREN 0x06 /* Write Enable */ ++#define CMD_W25_WRDI 0x04 /* Write Disable */ ++#define CMD_W25_RDSR 0x05 /* Read Status Register */ ++#define CMD_W25_WRSR 0x01 /* Write Status Register */ ++#define CMD_W25_READ 0x03 /* Read Data Bytes */ ++#define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ ++#define CMD_W25_PP 0x02 /* Page Program */ ++#define CMD_W25_SE 0x20 /* Sector (4K) Erase */ ++#define CMD_W25_BE 0xd8 /* Block (64K) Erase */ ++#define CMD_W25_CE 0xc7 /* Chip Erase */ ++#define CMD_W25_DP 0xb9 /* Deep Power-down */ ++#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */ ++ ++#define WINBOND_ID_W25X16 0x3015 ++#define WINBOND_ID_W25X32 0x3016 ++#define WINBOND_ID_W25X64 0x3017 ++ ++#define WINBOND_SR_WIP (1 << 0) /* Write-in-Progress */ ++ ++struct winbond_spi_flash_params { ++ uint16_t id; ++ /* Log2 of page size in power-of-two mode */ ++ uint8_t l2_page_size; ++ uint16_t pages_per_sector; ++ uint16_t sectors_per_block; ++ uint8_t nr_blocks; ++ const char *name; ++}; ++ ++struct winbond_spi_flash { ++ const struct winbond_spi_flash_params *params; ++ struct spi_flash flash; ++}; ++ ++static inline struct winbond_spi_flash * ++to_winbond_spi_flash(struct spi_flash *flash) ++{ ++ return container_of(flash, struct winbond_spi_flash, flash); ++} ++ ++static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { ++ { ++ .id = WINBOND_ID_W25X16, ++ .l2_page_size = 8, ++ .pages_per_sector = 16, ++ .sectors_per_block = 16, ++ .nr_blocks = 32, ++ .name = "W25X16", ++ }, ++ { ++ .id = WINBOND_ID_W25X32, ++ .l2_page_size = 8, ++ .pages_per_sector = 16, ++ .sectors_per_block = 16, ++ .nr_blocks = 64, ++ .name = "W25X32", ++ }, ++ { ++ .id = WINBOND_ID_W25X64, ++ .l2_page_size = 8, ++ .pages_per_sector = 16, ++ .sectors_per_block = 16, ++ .nr_blocks = 128, ++ .name = "W25X64", ++ }, ++}; ++ ++static int wait_state; ++ ++static int winbond_wait_ready(struct spi_flash *flash, unsigned long timeout) ++{ ++ struct spi_slave *spi = flash->spi; ++ unsigned long timebase; ++ int ret; ++ u8 status; ++ u8 cmd[4] = { CMD_W25_RDSR, 0xff, 0xff, 0xff }; ++ ++ ret = spi_xfer(spi, 32, &cmd[0], NULL, SPI_XFER_BEGIN); ++ if (ret) { ++ debug("SF: Failed to send command %02x: %d\n", cmd, ret); ++ return ret; ++ } ++ ++ timebase = get_timer(0); ++ do { ++ ret = spi_xfer(spi, 8, NULL, &status, 0); ++ if (ret) { ++ debug("SF: Failed to get status for cmd %02x: %d\n", cmd, ret); ++ return -1; ++ } ++ ++ if ((status & WINBOND_SR_WIP) == 0) ++ break; ++ else if ((status & WINBOND_SR_WIP) == 1) ++ wait_state++; ++ ++ } while (1 || (get_timer(timebase) < timeout)); ++ ++ spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); ++ ++ if ((status & WINBOND_SR_WIP) == 0) ++ return 0; ++ ++ debug("SF: Timed out on command %02x: %d\n", cmd, ret); ++ /* Timed out */ ++ return -1; ++} ++ ++/* ++ * Assemble the address part of a command for Winbond devices in ++ * non-power-of-two page size mode. ++ */ ++static void winbond_build_address(struct winbond_spi_flash *stm, u8 *cmd, u32 offset) ++{ ++ unsigned long page_addr; ++ unsigned long byte_addr; ++ unsigned long page_size; ++ unsigned int page_shift; ++ ++ /* ++ * The "extra" space per page is the power-of-two page size ++ * divided by 32. ++ */ ++ page_shift = stm->params->l2_page_size; ++ page_size = (1 << page_shift); ++ page_addr = offset / page_size; ++ byte_addr = offset % page_size; ++ ++ cmd[0] = page_addr >> (16 - page_shift); ++ cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8); ++ cmd[2] = byte_addr; ++} ++ ++static int winbond_read_fast(struct spi_flash *flash, ++ u32 offset, size_t len, void *buf) ++{ ++ struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); ++ u8 cmd[5]; ++ ++ cmd[0] = CMD_READ_ARRAY_FAST; ++ winbond_build_address(stm, cmd + 1, offset); ++ cmd[4] = 0x00; ++ ++ return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len); ++} ++ ++static int winbond_write(struct spi_flash *flash, ++ u32 offset, size_t len, const void *buf) ++{ ++ struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); ++ unsigned long page_addr; ++ unsigned long byte_addr; ++ unsigned long page_size; ++ unsigned int page_shift; ++ size_t chunk_len; ++ size_t actual; ++ int ret; ++ u8 cmd[4]; ++ ++ page_shift = stm->params->l2_page_size; ++ page_size = (1 << page_shift); ++ page_addr = offset / page_size; ++ byte_addr = offset % page_size; ++ ++ ret = spi_claim_bus(flash->spi); ++ if (ret) { ++ debug("SF: Unable to claim SPI bus\n"); ++ return ret; ++ } ++ ++ for (actual = 0; actual < len; actual += chunk_len) { ++ chunk_len = min(len - actual, page_size - byte_addr); ++ ++ cmd[0] = CMD_W25_PP; ++ cmd[1] = page_addr >> (16 - page_shift); ++ cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8); ++ cmd[3] = byte_addr; ++ debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n", ++ buf + actual, ++ cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); ++ ++ ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); ++ if (ret < 0) { ++ debug("SF: Enabling Write failed\n"); ++ goto out; ++ } ++ ++ ret = spi_flash_cmd_write(flash->spi, cmd, 4, ++ buf + actual, chunk_len); ++ if (ret < 0) { ++ debug("SF: Winbond Page Program failed\n"); ++ goto out; ++ } ++ ++ ret = winbond_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); ++ if (ret < 0) { ++ debug("SF: Winbond page programming timed out\n"); ++ goto out; ++ } ++ ++ page_addr++; ++ byte_addr = 0; ++ } ++ ++ printf("Number of times wait: %d\n", wait_state); ++ wait_state = 0; ++ ++ debug("SF: Winbond: Successfully programmed %u bytes @ 0x%x\n", ++ len, offset); ++ ret = 0; ++ ++out: ++ spi_release_bus(flash->spi); ++ return ret; ++} ++ ++int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) ++{ ++ struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); ++ unsigned long sector_size; ++ unsigned int page_shift; ++ size_t actual; ++ int ret; ++ u8 cmd[4]; ++ ++ /* ++ * This function currently uses sector erase only. ++ * probably speed things up by using bulk erase ++ * when possible. ++ */ ++ ++ page_shift = stm->params->l2_page_size; ++ sector_size = (1 << page_shift) * stm->params->pages_per_sector; ++ ++ if (offset % sector_size || len % sector_size) { ++ debug("SF: Erase offset/length not multiple of sector size\n"); ++ return -1; ++ } ++ ++ len /= sector_size; ++ cmd[0] = CMD_W25_SE; ++ ++ ret = spi_claim_bus(flash->spi); ++ if (ret) { ++ debug("SF: Unable to claim SPI bus\n"); ++ return ret; ++ } ++ ++ for (actual = 0; actual < len; actual++) { ++ winbond_build_address(stm, &cmd[1], offset + actual * sector_size); ++ printf("Erase: %02x %02x %02x %02x\n", ++ cmd[0], cmd[1], cmd[2], cmd[3]); ++ ++ ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); ++ if (ret < 0) { ++ debug("SF: Enabling Write failed\n"); ++ goto out; ++ } ++ ++ ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); ++ if (ret < 0) { ++ debug("SF: Winbond sector erase failed\n"); ++ goto out; ++ } ++ ++ ret = winbond_wait_ready(flash, 2 * CONFIG_SYS_HZ); /* Up to 2 seconds */ ++ if (ret < 0) { ++ debug("SF: Winbond sector erase timed out\n"); ++ goto out; ++ } ++ } ++ ++ debug("SF: Winbond: Successfully erased %u bytes @ 0x%x\n", ++ len * sector_size, offset); ++ ret = 0; ++ ++out: ++ spi_release_bus(flash->spi); ++ return ret; ++} ++ ++struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) ++{ ++ const struct winbond_spi_flash_params *params; ++ unsigned long page_size; ++ struct winbond_spi_flash *stm; ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) { ++ params = &winbond_spi_flash_table[i]; ++ if (params->id == ((idcode[1] << 8) | idcode[2])) ++ break; ++ } ++ ++ if (i == ARRAY_SIZE(winbond_spi_flash_table)) { ++ debug("SF: Unsupported Winbond ID %02x%02x\n", ++ idcode[1], idcode[2]); ++ return NULL; ++ } ++ ++ stm = malloc(sizeof(struct winbond_spi_flash)); ++ if (!stm) { ++ debug("SF: Failed to allocate memory\n"); ++ return NULL; ++ } ++ ++ stm->params = params; ++ stm->flash.spi = spi; ++ stm->flash.name = params->name; ++ ++ /* Assuming power-of-two page size initially. */ ++ page_size = 1 << params->l2_page_size; ++ ++ stm->flash.write = winbond_write; ++ stm->flash.erase = winbond_erase; ++ stm->flash.read = winbond_read_fast; ++ stm->flash.size = page_size * params->pages_per_sector ++ * params->sectors_per_block ++ * params->nr_blocks; ++ ++ debug("SF: Detected %s with page size %u, total %u bytes\n", ++ params->name, page_size, stm->flash.size); ++ ++ return &stm->flash; ++} +Index: u-boot-2009.01/drivers/spi/davinci_spi.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/drivers/spi/davinci_spi.c +@@ -0,0 +1,284 @@ ++/* ++ * Copyright (C) 2008 Sekhar Nori, Texas Instruments, Inc <www.ti.com> ++ * ++ * Driver for SPI controller on DaVinci. Based on atmel_spi.c ++ * by Atmel Corporation ++ * ++ * Copyright (C) 2007 Atmel Corporation ++ * ++ * 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 <spi.h> ++#include <malloc.h> ++ ++#include <asm/io.h> ++ ++#include <asm/arch/hardware.h> ++ ++#include "davinci_spi.h" ++ ++static unsigned int data1_reg_val; ++ ++ ++void spi_init() ++{ ++ /* do nothing */ ++ ++} ++ ++struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, ++ unsigned int max_hz, unsigned int mode) ++{ ++ struct davinci_spi_slave *ds; ++ void *regs; ++ unsigned int fmt0; ++ ++ ds = malloc(sizeof(struct davinci_spi_slave)); ++ if (!ds) ++ return NULL; ++ ++ ds->slave.bus = bus; ++ ds->slave.cs = cs; ++ ds->regs = CFG_SPI_BASE; ++ ds->freq = max_hz; ++ ++ return &ds->slave; ++} ++ ++void spi_free_slave(struct spi_slave *slave) ++{ ++ struct davinci_spi_slave *ds = to_davinci_spi(slave); ++ ++ free(ds); ++} ++ ++int spi_claim_bus(struct spi_slave *slave) ++{ ++ struct davinci_spi_slave *ds = to_davinci_spi(slave); ++ unsigned int scalar; ++ ++ /* Enable the SPI hardware */ ++ spi_writel(ds, GCR0, 0); ++ udelay(1000); ++ spi_writel(ds, GCR0, 1); ++ ++ /* Set master mode, powered up and not activated */ ++ spi_writel(ds, GCR1, 0x3); ++ ++ /* CS, CLK, SIMO and SOMI are functional pins */ ++ spi_writel(ds, PC0, (1 << 0) | (1 << 9) | (1 << 10) | (1 << 11)); ++ ++ /* setup format */ ++ scalar = ((CFG_SPI_CLK / ds->freq) - 1 ) & 0xFF; ++ ++ spi_writel(ds, FMT0, 8 | /* character length */ ++ (scalar << 8) | ++ (1 << 16) | /* clock signal delayed by half clk cycle */ ++ (0 << 17) | /* clock low in idle state - Mode 0 */ ++ (0 << 20)); /* MSB shifted out first */ ++ ++ /* hold cs active at end of transfer until explicitly de-asserted */ ++ data1_reg_val = (1 << 28) | (slave->cs << 16); ++ spi_writel(ds, DAT1, data1_reg_val); ++ ++ /* including a minor delay. No science here. Should be good even with ++ * no delay ++ */ ++ spi_writel(ds, DELAY, (50 << 24) | (50 << 16)); ++ ++ /* default chip select register */ ++ spi_writel(ds, DEF, 1); ++ ++ /* no interrupts */ ++ spi_writel(ds, INT0, 0); ++ spi_writel(ds, LVL, 0); ++ ++ /* enable SPI */ ++ spi_writel(ds, GCR1, spi_readl(ds, GCR1) | (1 << 24)); ++ ++ return 0; ++} ++ ++void spi_release_bus(struct spi_slave *slave) ++{ ++ struct davinci_spi_slave *ds = to_davinci_spi(slave); ++ ++ /* Disable the SPI hardware */ ++ spi_writel(ds, GCR0, 0); ++} ++ ++int spi_xfer(struct spi_slave *slave, unsigned int bitlen, ++ const void *dout, void *din, unsigned long flags) ++{ ++ struct davinci_spi_slave *ds = to_davinci_spi(slave); ++ unsigned int len_tx; ++ unsigned int len_rx; ++ unsigned int len; ++ int ret, i; ++ u32 status; ++ const u8 *txp = dout; ++ u8 *rxp = din; ++ u8 value, dummy = 0; ++ ++ ret = 0; ++ ++ if (bitlen == 0) ++ /* Finish any previously submitted transfers */ ++ goto out; ++ ++ /* ++ * It's not clear how non-8-bit-aligned transfers are supposed to be ++ * represented as a stream of bytes...this is a limitation of ++ * the current SPI interface - here we terminate on receiving such a ++ * transfer request. ++ */ ++ if (bitlen % 8) { ++ /* Errors always terminate an ongoing transfer */ ++ flags |= SPI_XFER_END; ++ goto out; ++ } ++ ++ len = bitlen / 8; ++ ++ /* do an empty read to clear the current contents */ ++ spi_readl(ds, BUF); ++ ++ /* keep writing and reading 1 byte until done */ ++ for (i = 0; i < len; i++) { ++ ++ /* wait till TXFULL is asserted */ ++ while(spi_readl(ds, BUF) & (1 << 29)); ++ ++ /* write the data */ ++ data1_reg_val &= ~0xFFFF; ++ if(txp) { ++ data1_reg_val |= *txp & 0xFF; ++ txp++; ++ } ++ ++ /* write to DAT1 is required to keep the serial transfer going */ ++ /* we just terminate when we reach the end */ ++ if((i == (len -1)) && (flags & SPI_XFER_END)) { ++ spi_writel(ds, DAT1, data1_reg_val & ~(1 << 28)); /* clear CS hold */ ++ } else { ++ spi_writel(ds, DAT1, data1_reg_val); ++ } ++ ++ ++ /* read the data - wait for data availability */ ++ while(spi_readl(ds, BUF) & (1 << 31)); ++ ++ if(rxp) { ++ *rxp = spi_readl(ds, BUF) & 0xFF; ++ rxp++; ++ } else { ++ spi_readl(ds, BUF); /* simply drop the read character */ ++ } ++ ++ } ++ ++ return 0; ++ ++out: ++ if (flags & SPI_XFER_END) { ++ spi_writel(ds, DAT1, data1_reg_val & ~(1 << 28)); ++ } ++ ++ return 0; ++} ++ ++ ++#ifdef CONFIG_CMD_EEPROM ++ ++/* ------------------------------------------------------------------------ * ++ * SPI ROM Definitions * ++ * ------------------------------------------------------------------------ */ ++#define SPIROM_SIZE 0x00008000 ++#define SPIROM_BASE 0x00000000 ++#define SPIROM_PAGESIZE 32 ++#define SPIROM_PAGEMASK 0xffffffc0 ++ ++/* ------------------------------------------------------------------------ * ++ * SPI ROM Commands * ++ * ------------------------------------------------------------------------ */ ++#define SPIROM_CMD_WRSR 0x01 ++#define SPIROM_CMD_WRITE 0x02 ++#define SPIROM_CMD_READ 0x03 ++#define SPIROM_CMD_WRDI 0x04 ++#define SPIROM_CMD_RDSR 0x05 ++#define SPIROM_CMD_WREN 0x06 ++ ++static struct spi_slave *slave; ++ ++void spi_init_f(void) ++{ ++ slave = spi_setup_slave(0, 0, 1*1024*1024, 0); ++ spi_claim_bus(slave); ++} ++ ++static char spirombuf[3]; ++ ++/* ------------------------------------------------------------------------ * ++ * spirom_status( ) * ++ * ------------------------------------------------------------------------ */ ++static unsigned char spi_get_status( ) ++{ ++ /* Issue read status command */ ++ spirombuf[0] = SPIROM_CMD_RDSR; ++ spirombuf[1] = 0; ++ ++ spi_xfer(slave, (2)*8, spirombuf, spirombuf, SPI_XFER_BEGIN | SPI_XFER_END); ++ ++ return spirombuf[1]; ++} ++ ++ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len) ++{ ++ ++ spirombuf[0] = SPIROM_CMD_WREN; ++ spi_xfer(slave, 1*8, spirombuf, NULL, SPI_XFER_BEGIN | SPI_XFER_END); ++ ++ /* Create command block for program operation */ ++ spirombuf[0] = SPIROM_CMD_WRITE; ++ spirombuf[1] = addr[0]; ++ spirombuf[2] = addr[1]; ++ ++ spi_xfer(slave, 3 * 8, spirombuf, NULL, SPI_XFER_BEGIN); ++ spi_xfer(slave, len * 8, buffer, NULL, SPI_XFER_END); ++ ++ /* Wait while busy */ ++ while( (spi_get_status( ) & 0x01 ) ); ++ ++ return len; ++} ++ ++ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len) ++{ ++ spirombuf[0] = 0x3; ++ spirombuf[1] = addr[0]; ++ spirombuf[2] = addr[1]; ++ ++ spi_xfer(slave, 3*8, spirombuf, NULL, SPI_XFER_BEGIN); ++ spi_xfer(slave, len*8, NULL, buffer, SPI_XFER_END); ++ ++ return len; ++} ++ ++#endif +Index: u-boot-2009.01/drivers/spi/davinci_spi.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01/drivers/spi/davinci_spi.h +@@ -0,0 +1,46 @@ ++/* ++ * Register definitions for the DaVinci SPI Controller ++ */ ++ ++/* Register offsets */ ++#define DAVINCI_SPI_GCR0 0x0000 ++#define DAVINCI_SPI_GCR1 0x0004 ++#define DAVINCI_SPI_INT0 0x0008 ++#define DAVINCI_SPI_LVL 0x000c ++#define DAVINCI_SPI_FLG 0x0010 ++#define DAVINCI_SPI_PC0 0x0014 ++#define DAVINCI_SPI_PC1 0x0018 ++#define DAVINCI_SPI_PC2 0x001c ++#define DAVINCI_SPI_PC3 0x0020 ++#define DAVINCI_SPI_PC4 0x0024 ++#define DAVINCI_SPI_PC5 0x0028 ++#define DAVINCI_SPI_DAT0 0x0038 ++#define DAVINCI_SPI_DAT1 0x003c ++#define DAVINCI_SPI_BUF 0x0040 ++#define DAVINCI_SPI_EMU 0x0044 ++#define DAVINCI_SPI_DELAY 0x0048 ++#define DAVINCI_SPI_DEF 0x004c ++#define DAVINCI_SPI_FMT0 0x0050 ++#define DAVINCI_SPI_FMT1 0x0054 ++#define DAVINCI_SPI_FMT2 0x0058 ++#define DAVINCI_SPI_FMT3 0x005c ++#define DAVINCI_SPI_INTVEC0 0x0060 ++#define DAVINCI_SPI_INTVEC1 0x0064 ++ ++struct davinci_spi_slave { ++ struct spi_slave slave; ++ void *regs; ++ u32 mr; ++ unsigned int freq; ++}; ++ ++static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) ++{ ++ return container_of(slave, struct davinci_spi_slave, slave); ++} ++ ++#define spi_readl(as, reg) \ ++ readl(CFG_SPI_BASE + DAVINCI_SPI_##reg) ++#define spi_writel(as, reg, value) \ ++ writel(value, CFG_SPI_BASE + DAVINCI_SPI_##reg) ++ +Index: u-boot-2009.01/drivers/spi/spirom.c +=================================================================== +--- /dev/null ++++ u-boot-2009.01/drivers/spi/spirom.c +@@ -0,0 +1,212 @@ ++/* ++ * Copyright 2007 b7 Spectrum Digital Incorporated. ++ * All rights reserved. Property of Spectrum Digital Incorporated. ++ */ ++ ++/* ++ * SPI ROM interface ++ * ++ */ ++ ++#include "spirom.h" ++ ++static Uint8 spirombuf[SPIROM_PAGESIZE + 5]; ++static Uint8 statusbuf[8]; ++static Uint32 spidat1; ++ ++/* ------------------------------------------------------------------------ * ++ * * ++ * _wait( delay ) * ++ * Wait in a software loop for 'x' delay * ++ * * ++ * ------------------------------------------------------------------------ */ ++void DAVINCIHD_wait( Uint32 delay ) ++{ ++ volatile Uint32 i; ++ for ( i = 0 ; i < delay ; i++ ){ }; ++} ++ ++ ++/* ------------------------------------------------------------------------ * ++ * spirom_init( ) * ++ * ------------------------------------------------------------------------ */ ++void spirom_init( ) ++{ ++ /* Reset SPI */ ++ SPI_SPIGCR0 = 0; ++ _wait( 1000 ); ++ ++ /* Release SPI */ ++ SPI_SPIGCR0 = 1; ++ ++ /* SPI 4-Pin Mode setup */ ++ SPI_SPIGCR1 = 0 ++ | ( 0 << 24 ) ++ | ( 0 << 16 ) ++ | ( 1 << 1 ) ++ | ( 1 << 0 ); ++ ++ SPI_SPIPC0 = 0 ++ | ( 1 << 11 ) // DI ++ | ( 1 << 10 ) // DO ++ | ( 1 << 9 ) // CLK ++ | ( 1 << 1 ) // EN1 ++ | ( 1 << 0 ); // EN0 ++ ++ SPI_SPIFMT0 = 0 ++ | ( 0 << 20 ) // SHIFTDIR ++ | ( 0 << 17 ) // Polarity ++ | ( 1 << 16 ) // Phase ++ | ( 50 << 8 ) // Prescale ++ | ( 8 << 0 ); // Char Len ++ ++ spidat1 = 0 ++ | ( 1 << 28 ) // CSHOLD ++ | ( 0 << 24 ) // Format [0] ++ | ( 2 << 16 ) // CSNR [only CS0 enbled] ++ | ( 0 << 0 ); // ++ ++ SPI_SPIDAT1 = spidat1; ++ ++ SPI_SPIDELAY = 0 ++ | ( 8 << 24 ) // C2TDELAY ++ | ( 8 << 16 ); // T2CDELAY ++ ++ SPI_SPIDEF = 0 ++ | ( 1 << 1 ) // EN1 inactive high ++ | ( 1 << 0 ); // EN0 inactive high ++ ++ SPI_SPIINT = 0 ++ | ( 0 << 16 ) // ++ | ( 0 << 8 ) // ++ | ( 0 << 6 ) // ++ | ( 1 << 4 ); // ++ ++ SPI_SPILVL = 0 ++ | ( 0 << 8 ) // EN0 ++ | ( 0 << 6 ) // EN0 ++ | ( 0 << 4 ); // EN0 ++ ++ ++ /* Enable SPI */ ++ SPI_SPIGCR1 |= ( 1 << 24 ); ++} ++ ++/* ------------------------------------------------------------------------ * ++ * spirom_cycle( buf, len ) * ++ * * ++ * Execute a SPI spirom data transfer cycle. Each byte in buf is shifted * ++ * out and replaced with data coming back from the spirom. * ++ * ------------------------------------------------------------------------ */ ++void spirom_cycle( Uint8 *buf, Uint16 len ) ++{ ++ Uint16 i; ++ ++ /* Clear any old data */ ++ SPI_SPIBUF; ++ ++ /* SPIROM access cycle */ ++ for ( i = 0 ; i <= len ; i++ ) ++ { ++ /* Wait for transmit ready */ ++ while ( SPI_SPIBUF & 0x10000000 ); ++ ++ if ( i == len ) ++ SPI_SPIDAT1 = ( spidat1 & 0x0ffcffff ) | buf[i]; ++ else ++ SPI_SPIDAT1 = spidat1 | buf[i]; ++ ++ /* Wait for receive data ready */ ++ while ( SPI_SPIBUF & 0x80000000 ); ++ ++ /* Read 1 byte */ ++ buf[i] = SPI_SPIBUF; ++ } ++} ++ ++/* ------------------------------------------------------------------------ * ++ * spirom_status( ) * ++ * ------------------------------------------------------------------------ */ ++Uint8 spirom_status( ) ++{ ++ /* Issue read status command */ ++ statusbuf[0] = SPIROM_CMD_RDSR; ++ statusbuf[1] = 0; ++ ++ spirom_cycle( statusbuf, 2 ); ++ ++ return statusbuf[1]; ++} ++ ++/* ------------------------------------------------------------------------ * ++ * spirom_read( src, dst, length ) * ++ * ------------------------------------------------------------------------ */ ++void spirom_read( Uint16 src, Uint32 dst, Uint32 length ) ++{ ++ Int32 i; ++ Uint8 *psrc, *pdst; ++ ++ // Setup command ++ spirombuf[0] = SPIROM_CMD_READ; ++ spirombuf[1] = ( src >> 8 ); ++ spirombuf[2] = ( src >> 0 ); ++ ++ // Execute spirom read cycle ++ spirom_cycle( spirombuf, length + 3 ); ++ ++ // Copy returned data ++ pdst = ( Uint8 * )dst; ++ psrc = spirombuf + 3; ++ for ( i = 0 ; i < length ; i++ ) ++ *pdst++ = *psrc++; ++} ++ ++/* ------------------------------------------------------------------------ * ++ * spirom_write( src, dst, length ) * ++ * ------------------------------------------------------------------------ */ ++void spirom_write( Uint32 src, Uint16 dst, Uint32 length ) ++{ ++ Int32 i; ++ Int32 bytes_left; ++ Int32 bytes_to_program; ++ Uint8 *psrc; ++ ++ /* Establish source */ ++ psrc = ( Uint8 * )src; ++ bytes_left = length; ++ ++ while ( bytes_left > 0 ) ++ { ++ bytes_to_program = bytes_left; ++ ++ /* Most to program is SPIROM_CMD_BLOCKSIZE */ ++ if ( bytes_to_program > SPIROM_PAGESIZE ) ++ bytes_to_program = SPIROM_PAGESIZE; ++ ++ /* Make sure you don't run off the end of a block */ ++ if ( ( dst & SPIROM_PAGEMASK ) != ( ( dst + bytes_to_program ) & SPIROM_PAGEMASK ) ) ++ bytes_to_program -= ( dst + bytes_to_program ) - ( ( dst + bytes_to_program ) & SPIROM_PAGEMASK ); ++ ++ /* Issue WPEN */ ++ spirombuf[0] = SPIROM_CMD_WREN; ++ spirom_cycle( spirombuf, 0 ); ++ ++ /* Create command block for program operation */ ++ spirombuf[0] = SPIROM_CMD_WRITE; ++ spirombuf[1] = ( Uint8 )( dst >> 8 ); ++ spirombuf[2] = ( Uint8 )( dst ); ++ ++ for ( i = 0 ; i < bytes_to_program ; i++ ) ++ spirombuf[3+i] = *psrc++; ++ ++ /* Execute write command */ ++ spirom_cycle( spirombuf, bytes_to_program + 2 ); ++ ++ /* Wait while busy */ ++ while( ( spirom_status( ) & 0x01 ) ); ++ ++ /* Get ready for next iteration */ ++ bytes_left -= bytes_to_program; ++ dst += bytes_to_program; ++ } ++} +Index: u-boot-2009.01/drivers/spi/spirom.h +=================================================================== +--- /dev/null ++++ u-boot-2009.01/drivers/spi/spirom.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright 2007 by Spectrum Digital Incorporated. ++ * All rights reserved. Property of Spectrum Digital Incorporated. ++ */ ++ ++/* ++ * SPI ROM header file ++ * ++ */ ++ ++#ifndef SPIROM_ ++#define SPIROM_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "davincihd.h" ++ ++/* ------------------------------------------------------------------------ * ++ * SPI ROM Definitions * ++ * ------------------------------------------------------------------------ */ ++#define SPIROM_SIZE 0x00008000 ++#define SPIROM_BASE 0x00000000 ++#define SPIROM_PAGESIZE 32 ++#define SPIROM_PAGEMASK 0xffffffc0 ++ ++/* ------------------------------------------------------------------------ * ++ * SPI ROM Commands * ++ * ------------------------------------------------------------------------ */ ++#define SPIROM_CMD_WRSR 0x01 ++#define SPIROM_CMD_WRITE 0x02 ++#define SPIROM_CMD_READ 0x03 ++#define SPIROM_CMD_WRDI 0x04 ++#define SPIROM_CMD_RDSR 0x05 ++#define SPIROM_CMD_WREN 0x06 ++ ++/* ------------------------------------------------------------------------ * ++ * SPI Controller * ++ * ------------------------------------------------------------------------ */ ++#define SPI_BASE 0x01c66800 ++#define SPI_SPIGCR0 *( volatile Uint32* )( SPI_BASE + 0x0 ) ++#define SPI_SPIGCR1 *( volatile Uint32* )( SPI_BASE + 0x4 ) ++#define SPI_SPIINT *( volatile Uint32* )( SPI_BASE + 0x8 ) ++#define SPI_SPILVL *( volatile Uint32* )( SPI_BASE + 0xc ) ++#define SPI_SPIFLG *( volatile Uint32* )( SPI_BASE + 0x10 ) ++#define SPI_SPIPC0 *( volatile Uint32* )( SPI_BASE + 0x14 ) ++#define SPI_SPIPC2 *( volatile Uint32* )( SPI_BASE + 0x1c ) ++#define SPI_SPIDAT1_TOP *( volatile Uint16* )( SPI_BASE + 0x3c ) ++#define SPI_SPIDAT1 *( volatile Uint32* )( SPI_BASE + 0x3c ) ++#define SPI_SPIDAT1_PTR16 *( volatile Uint16* )( SPI_BASE + 0x3e ) ++#define SPI_SPIDAT1_PTR8 *( volatile Uint8* ) ( SPI_BASE + 0x3f ) ++#define SPI_SPIBUF *( volatile Uint32* )( SPI_BASE + 0x40 ) ++#define SPI_SPIBUF_PTR16 *( volatile Uint16* )( SPI_BASE + 0x42 ) ++#define SPI_SPIBUF_PTR8 *( volatile Uint8* ) ( SPI_BASE + 0x43 ) ++#define SPI_SPIEMU *( volatile Uint32* )( SPI_BASE + 0x44 ) ++#define SPI_SPIDELAY *( volatile Uint32* )( SPI_BASE + 0x48 ) ++#define SPI_SPIDEF *( volatile Uint32* )( SPI_BASE + 0x4c ) ++#define SPI_SPIFMT0 *( volatile Uint32* )( SPI_BASE + 0x50 ) ++#define SPI_SPIFMT1 *( volatile Uint32* )( SPI_BASE + 0x54 ) ++#define SPI_SPIFMT2 *( volatile Uint32* )( SPI_BASE + 0x58 ) ++#define SPI_SPIFMT3 *( volatile Uint32* )( SPI_BASE + 0x5c ) ++#define SPI_INTVEC0 *( volatile Uint32* )( SPI_BASE + 0x60 ) ++#define SPI_INTVEC1 *( volatile Uint32* )( SPI_BASE + 0x64 ) ++ ++/* ------------------------------------------------------------------------ * ++ * Prototype * ++ * ------------------------------------------------------------------------ */ ++void spirom_init( ); ++void spirom_read( Uint16 src, Uint32 dst, Uint32 length ); ++void spirom_write( Uint32 src, Uint16 dst, Uint32 length ); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +Index: u-boot-2009.01/net/eth.c +=================================================================== +--- u-boot-2009.01.orig/net/eth.c ++++ u-boot-2009.01/net/eth.c +@@ -469,7 +469,7 @@ extern int at91rm9200_miiphy_initialize( + extern int emac4xx_miiphy_initialize(bd_t *bis); + extern int mcf52x2_miiphy_initialize(bd_t *bis); + extern int ns7520_miiphy_initialize(bd_t *bis); +-extern int davinci_eth_miiphy_initialize(bd_t *bis); ++extern int dm644x_eth_miiphy_initialize(bd_t *bis); + + + int eth_initialize(bd_t *bis) +@@ -491,7 +491,7 @@ int eth_initialize(bd_t *bis) + ns7520_miiphy_initialize(bis); + #endif + #if defined(CONFIG_DRIVER_TI_EMAC) +- davinci_eth_miiphy_initialize(bis); ++ dm644x_eth_miiphy_initialize(bis); + #endif + return 0; + } +Index: u-boot-2009.01/drivers/mtd/spi/Makefile +=================================================================== +--- u-boot-2009.01.orig/drivers/mtd/spi/Makefile ++++ u-boot-2009.01/drivers/mtd/spi/Makefile +@@ -28,6 +28,7 @@ LIB := $(obj)libspi_flash.a + COBJS-$(CONFIG_SPI_FLASH) += spi_flash.o + COBJS-$(CONFIG_SPI_FLASH_ATMEL) += atmel.o + COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o ++COBJS-$(CONFIG_SPI_FLASH_WINBOND) += winbond.o + + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) +Index: u-boot-2009.01/drivers/spi/Makefile +=================================================================== +--- u-boot-2009.01.orig/drivers/spi/Makefile ++++ u-boot-2009.01/drivers/spi/Makefile +@@ -29,6 +29,7 @@ COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o + COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o + COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o + COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o ++COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o + + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) +Index: u-boot-2009.01/drivers/mtd/spi/spi_flash.c +=================================================================== +--- u-boot-2009.01.orig/drivers/mtd/spi/spi_flash.c ++++ u-boot-2009.01/drivers/mtd/spi/spi_flash.c +@@ -3,7 +3,7 @@ + * + * Copyright (C) 2008 Atmel Corporation + */ +-#define DEBUG ++/*#define DEBUG*/ + #include <common.h> + #include <malloc.h> + #include <spi.h> +@@ -134,6 +134,11 @@ struct spi_flash *spi_flash_probe(unsign + flash = spi_flash_probe_atmel(spi, idcode); + break; + #endif ++#ifdef CONFIG_SPI_FLASH_WINBOND ++ case 0xef: ++ flash = spi_flash_probe_winbond(spi, idcode); ++ break; ++#endif + #ifdef CONFIG_SPI_FLASH_STMICRO + case 0x20: + flash = spi_flash_probe_stmicro(spi, idcode); +Index: u-boot-2009.01/common/cmd_nvedit.c +=================================================================== +--- u-boot-2009.01.orig/common/cmd_nvedit.c ++++ u-boot-2009.01/common/cmd_nvedit.c +@@ -549,6 +549,7 @@ int getenv_r (char *name, char *buf, uns + #if ((defined(CONFIG_ENV_IS_IN_NVRAM) || defined(CONFIG_ENV_IS_IN_EEPROM) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \ ++ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_SF)) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))) \ + && !defined(CONFIG_ENV_IS_NOWHERE)) + int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +@@ -605,6 +606,7 @@ U_BOOT_CMD( + #if ((defined(CONFIG_ENV_IS_IN_NVRAM) || defined(CONFIG_ENV_IS_IN_EEPROM) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \ ++ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_SF)) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))) \ + && !defined(CONFIG_ENV_IS_NOWHERE)) + U_BOOT_CMD( +Index: u-boot-2009.01/common/cmd_sf.c +=================================================================== +--- u-boot-2009.01.orig/common/cmd_sf.c ++++ u-boot-2009.01/common/cmd_sf.c +@@ -29,6 +29,11 @@ static int do_spi_flash_probe(int argc, + if (argc < 2) + goto usage; + ++ if(flash) { ++ printf("SPI flash already probed\n"); ++ goto probe_done; ++ } ++ + cs = simple_strtoul(argv[1], &endp, 0); + if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) + goto usage; +@@ -63,6 +68,7 @@ static int do_spi_flash_probe(int argc, + spi_flash_free(flash); + flash = new; + ++probe_done: + printf("%u KiB %s at %u:%u is now current device\n", + flash->size >> 10, flash->name, bus, cs); + +Index: u-boot-2009.01/include/linux/mtd/nand.h +=================================================================== +--- u-boot-2009.01.orig/include/linux/mtd/nand.h ++++ u-boot-2009.01/include/linux/mtd/nand.h +@@ -135,6 +135,15 @@ typedef enum { + NAND_ECC_HW_SYNDROME, + } nand_ecc_modes_t; + ++struct page_layout_item { ++ int length; ++ enum { ++ ITEM_TYPE_DATA, ++ ITEM_TYPE_OOB, ++ ITEM_TYPE_ECC, ++ } type; ++}; ++ + /* + * Constants for Hardware ECC + */ +@@ -144,6 +153,9 @@ typedef enum { + #define NAND_ECC_WRITE 1 + /* Enable Hardware ECC before syndrom is read back from flash */ + #define NAND_ECC_READSYN 2 ++#define NAND_ECC_WRITESYN 3 ++#define NAND_ECC_READOOB 4 ++#define NAND_ECC_WRITEOOB 5 + + /* Bit mask for flags passed to do_nand_read_ecc */ + #define NAND_GET_DEVICE 0x80 diff --git a/patches/series b/patches/series new file mode 100644 index 0000000000..83afb9073a --- /dev/null +++ b/patches/series @@ -0,0 +1,2 @@ +primus_port.patch +freon_port.patch |