diff options
author | wdenk <wdenk> | 2004-01-03 00:43:19 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2004-01-03 00:43:19 +0000 |
commit | 3a473b2a6523db9cdf2b5aed22d9730b4ebc5693 (patch) | |
tree | 40da84736871e773141ea971d832bf0c908d59b7 /board/Marvell/common | |
parent | b6e4c4033c4f889c452c511d38c77808c67f9cf7 (diff) | |
download | u-boot-imx-3a473b2a6523db9cdf2b5aed22d9730b4ebc5693.zip u-boot-imx-3a473b2a6523db9cdf2b5aed22d9730b4ebc5693.tar.gz u-boot-imx-3a473b2a6523db9cdf2b5aed22d9730b4ebc5693.tar.bz2 |
* Patch by Ronen Shitrit, 10 Dec 2003:
Add support for the Marvell DB64360 / DB64460 development boards
* Patch by Detlev Zundel, 10 Dec 2003:
fix dependency problem in examples/Makefile
Diffstat (limited to 'board/Marvell/common')
-rw-r--r-- | board/Marvell/common/bootseq.txt | 94 | ||||
-rw-r--r-- | board/Marvell/common/ecctest.c | 133 | ||||
-rw-r--r-- | board/Marvell/common/flash.c | 1072 | ||||
-rw-r--r-- | board/Marvell/common/i2c.c | 532 | ||||
-rw-r--r-- | board/Marvell/common/i2c.h | 32 | ||||
-rw-r--r-- | board/Marvell/common/intel_flash.c | 269 | ||||
-rw-r--r-- | board/Marvell/common/intel_flash.h | 186 | ||||
-rw-r--r-- | board/Marvell/common/memory.c | 1390 | ||||
-rw-r--r-- | board/Marvell/common/misc.S | 235 | ||||
-rw-r--r-- | board/Marvell/common/ns16550.c | 66 | ||||
-rw-r--r-- | board/Marvell/common/ns16550.h | 102 | ||||
-rw-r--r-- | board/Marvell/common/ppc_error_no.h | 164 | ||||
-rw-r--r-- | board/Marvell/common/serial.c | 178 | ||||
-rw-r--r-- | board/Marvell/common/serial.h | 89 |
14 files changed, 4542 insertions, 0 deletions
diff --git a/board/Marvell/common/bootseq.txt b/board/Marvell/common/bootseq.txt new file mode 100644 index 0000000..648c2ff --- /dev/null +++ b/board/Marvell/common/bootseq.txt @@ -0,0 +1,94 @@ +(cpu/mpc7xxx/start.S) + +start: + b boot_cold + +start_warm: + b boot_warm + + +boot_cold: +boot_warm: + clear bats + init l2 (if enabled) + init altivec (if enabled) + invalidate l2 (if enabled) + setup bats (from defines in config_EVB) + enable_addr_trans: (if MMU enabled) + enable MSR_IR and MSR_DR + jump to in_flash + +in_flash: + enable l1 dcache + gal_low_init: (board/evb64260/sdram_init.S) + config SDRAM (CFG, TIMING, DECODE) + init scratch regs (810 + 814) + + detect DIMM0 (bank 0 only) + config SDRAM_PARA0 to 256/512Mbit + bl sdram_op_mode + detect bank0 width + write scratch reg 810 + config SDRAM_PARA0 with results + config SDRAM_PARA1 with results + + detect DIMM1 (bank 2 only) + config SDRAM_PARA2 to 256/512Mbit + detect bank2 width + write scratch reg 814 + config SDRAM_PARA2 with results + config SDRAM_PARA3 with results + + setup device bus timings/width + setup boot device timings/width + + setup CPU_CONF (0x0) + setup cpu master control register 0x160 + setup PCI0 TIMEOUT + setup PCI1 TIMEOUT + setup PCI0 BAR + setup PCI1 BAR + + setup MPP control 0-3 + setup GPP level control + setup Serial ports multiplex + + setup stack pointer (r1) + setup GOT + call cpu_init_f + debug leds + board_init_f: (common/board.c) + board_pre_init: + remap gt regs? + map PCI mem/io + map device space + clear out interupts + init_timebase + env_init + serial_init + console_init_f + display_options + initdram: (board/evb64260/evb64260.c) + detect memory + for each bank: + dram_size() + setup PCI slave memory mappings + setup SCS + setup monitor + alloc board info struct + init bd struct + relocate_code: (cpu/mpc7xxx/start.S) + copy,got,clearbss + board_init_r(bd, dest_addr) (common/board.c) + setup bd function pointers + trap_init + flash_init: (board/evb64260/flash.c) + setup bd flash info + cpu_init_r: (cpu/mpc7xxx/cpu_init.c) + nothing + mem_malloc_init + malloc_bin_reloc + spi_init (r or f)??? (CFG_ENV_IS_IN_EEPROM) + env_relocated + misc_init_r(bd): (board/evb64260/evb64260.c) + mpsc_init2 diff --git a/board/Marvell/common/ecctest.c b/board/Marvell/common/ecctest.c new file mode 100644 index 0000000..6247b45 --- /dev/null +++ b/board/Marvell/common/ecctest.c @@ -0,0 +1,133 @@ +indent: Standard input:49: Warning:old style assignment ambiguity in "=*". Assuming "= *" + +/* + * (C) Copyright 2001 + * + * 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 + */ + +#ifdef ECC_TEST +static inline void ecc_off (void) +{ + *(volatile int *) (INTERNAL_REG_BASE_ADDR + 0x4b4) &= ~0x00200000; +} + +static inline void ecc_on (void) +{ + *(volatile int *) (INTERNAL_REG_BASE_ADDR + 0x4b4) |= 0x00200000; +} + +static int putshex (const char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + printf ("%02x", buf[i]); + } + return 0; +} + +static int char_memcpy (void *d, const void *s, int len) +{ + int i; + char *cd = d; + const char *cs = s; + + for (i = 0; i < len; i++) { + *(cd++) = *(cs++); + } + return 0; +} + +static int memory_test (char *buf) +{ + const char src[][16] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, + {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, + {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, + {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, + {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, + {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, + {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + }; + const int foo[] = { 0 }; + int i, j, a; + + printf ("\ntest @ %d %p\n", foo[0], buf); + for (i = 0; i < 12; i++) { + for (a = 0; a < 8; a++) { + const char *s = src[i] + a; + int align = (unsigned) (s) & 0x7; + + /* ecc_off(); */ + memcpy (buf, s, 8); + /* ecc_on(); */ + putshex (s, 8); + if (memcmp (buf, s, 8)) { + putc ('\n'); + putshex (buf, 8); + printf (" [FAIL] (%p) align=%d\n", s, align); + for (j = 0; j < 8; j++) { + s[j] == buf[j] ? puts (" ") : + printf ("%02x", + (s[j]) ^ (buf[j])); + } + putc ('\n'); + } else { + printf (" [PASS] (%p) align=%d\n", s, align); + } + /* ecc_off(); */ + char_memcpy (buf, s, 8); + /* ecc_on(); */ + putshex (s, 8); + if (memcmp (buf, s, 8)) { + putc ('\n'); + putshex (buf, 8); + printf (" [FAIL] (%p) align=%d\n", s, align); + for (j = 0; j < 8; j++) { + s[j] == buf[j] ? puts (" ") : + printf ("%02x", + (s[j]) ^ (buf[j])); + } + putc ('\n'); + } else { + printf (" [PASS] (%p) align=%d\n", s, align); + } + } + } + + return 0; +} +#endif diff --git a/board/Marvell/common/flash.c b/board/Marvell/common/flash.c new file mode 100644 index 0000000..c2c5b76 --- /dev/null +++ b/board/Marvell/common/flash.c @@ -0,0 +1,1072 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * 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 + */ + +/* + * flash.c - flash support for the 512k, 8bit boot flash + and the 8MB 32bit extra flash on the DB64360 + * most of this file was based on the existing U-Boot + * flash drivers. + * + * written or collected and sometimes rewritten by + * Ingo Assmus <ingo.assmus@keymile.com> + * + */ + +#include <common.h> +#include <mpc8xx.h> +#include "../include/mv_gen_reg.h" +#include "../include/memory.h" +#include "intel_flash.h" + +#define FLASH_ROM 0xFFFD /* unknown flash type */ +#define FLASH_RAM 0xFFFE /* unknown flash type */ +#define FLASH_MAN_UNKNOWN 0xFFFF0000 + +/* #define DEBUG */ + +/* Intel flash commands */ +int flash_erase_intel (flash_info_t * info, int s_first, int s_last); +int write_word_intel (bank_addr_t addr, bank_word_t value); + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (int portwidth, vu_long * addr, + flash_info_t * info); +static int write_word (flash_info_t * info, ulong dest, ulong data); +static void flash_get_offsets (ulong base, flash_info_t * info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned int i; + unsigned long size_b0 = 0, size_b1 = 0; + unsigned long base, flash_size; + + /* Init: no FLASHes known */ + for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* the boot flash */ + base = CFG_FLASH_BASE; + size_b0 = + flash_get_size (CFG_BOOT_FLASH_WIDTH, (vu_long *) base, + &flash_info[0]); + + printf ("[%ldkB@%lx] ", size_b0 / 1024, base); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n", base, size_b0, size_b0 << 20); + } + + base = memoryGetDeviceBaseAddress (CFG_EXTRA_FLASH_DEVICE); +/* base = memoryGetDeviceBaseAddress(DEV_CS3_BASE_ADDR);*/ + for (i = 1; i < CFG_MAX_FLASH_BANKS; i++) { + unsigned long size = + flash_get_size (CFG_EXTRA_FLASH_WIDTH, + (vu_long *) base, &flash_info[i]); + + printf ("[%ldMB@%lx] ", size >> 20, base); + + if (flash_info[i].flash_id == FLASH_UNKNOWN) { + if (i == 1) { + printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n", base, size_b1, size_b1 << 20); + } + break; + } + size_b1 += size; + base += size; + } + + flash_size = size_b0 + size_b1; + return flash_size; +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t * info) +{ + int i; + int sector_size; + + if (!info->sector_count) + return; + + /* set up sector start address table */ + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + case FLASH_28F128J3A: + case FLASH_28F640J3A: + case FLASH_RAM: + /* this chip has uniformly spaced sectors */ + sector_size = info->size / info->sector_count; + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * sector_size); + break; + default: + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00008000; + info->start[2] = base + 0x0000C000; + info->start[3] = base + 0x00010000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = + base + (i * 0x00020000) - 0x00060000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x00010000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00020000; + } + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_STM: + printf ("STM "); + break; + case FLASH_MAN_AMD: + printf ("AMD "); + break; + case FLASH_MAN_FUJ: + printf ("FUJITSU "); + break; + case FLASH_MAN_INTEL: + printf ("INTEL "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + printf ("AM29LV040B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400B: + printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: + printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: + printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: + printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: + printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: + printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: + printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: + printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + case FLASH_28F640J3A: + printf ("28F640J3A (64 Mbit)\n"); + break; + case FLASH_28F128J3A: + printf ("28F128J3A (128 Mbit)\n"); + break; + case FLASH_ROM: + printf ("ROM\n"); + break; + case FLASH_RAM: + printf ("RAM\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + if ((info->size >> 20) > 0) { + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + } else { + printf (" Size: %ld kB in %d Sectors\n", + info->size >> 10, info->sector_count); + } + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + return; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +static inline void flash_cmd (int width, volatile unsigned char *addr, + int offset, unsigned char cmd) +{ + /* supports 1x8, 1x16, and 2x16 */ + /* 2x8 and 4x8 are not supported */ + if (width == 4) { + /* assuming chips are in 16 bit mode */ + /* 2x16 */ + unsigned long cmd32 = (cmd << 16) | cmd; + + *(volatile unsigned long *) (addr + offset * 2) = cmd32; + } else { + /* 1x16 or 1x8 */ + *(volatile unsigned char *) (addr + offset) = cmd; + } +} + +static ulong +flash_get_size (int portwidth, vu_long * addr, flash_info_t * info) +{ + short i; + volatile unsigned char *caddr = (unsigned char *) addr; + volatile unsigned short *saddr = (unsigned short *) addr; + volatile unsigned long *laddr = (unsigned long *) addr; + char old[2], save; + ulong id = 0, manu = 0, base = (ulong) addr; + +#ifdef DEBUG + printf ("%s: enter\n", __FUNCTION__); +#endif + info->portwidth = portwidth; + + save = *caddr; + + flash_cmd (portwidth, caddr, 0, 0xf0); + flash_cmd (portwidth, caddr, 0, 0xf0); + + udelay (10); + + old[0] = caddr[0]; + old[1] = caddr[1]; + + + if (old[0] != 0xf0) { + flash_cmd (portwidth, caddr, 0, 0xf0); + flash_cmd (portwidth, caddr, 0, 0xf0); + + udelay (10); + + if (*caddr == 0xf0) { + /* this area is ROM */ + *caddr = save; + info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN; + info->sector_count = 8; + info->size = 0x80000; + flash_get_offsets (base, info); + return info->size; + } + } else { + *caddr = 0; + + udelay (10); + + if (*caddr == 0) { + /* this area is RAM */ + *caddr = save; + info->flash_id = FLASH_RAM + FLASH_MAN_UNKNOWN; + info->sector_count = 8; + info->size = 0x80000; + flash_get_offsets (base, info); + return info->size; + } + flash_cmd (portwidth, caddr, 0, 0xf0); + + udelay (10); + } + + /* Write auto select command: read Manufacturer ID */ + flash_cmd (portwidth, caddr, 0x555, 0xAA); + flash_cmd (portwidth, caddr, 0x2AA, 0x55); + flash_cmd (portwidth, caddr, 0x555, 0x90); + + udelay (10); + + if ((caddr[0] == old[0]) && (caddr[1] == old[1])) { + + /* this area is ROM */ + info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN; + info->sector_count = 8; + info->size = 0x80000; + flash_get_offsets (base, info); + return info->size; +#ifdef DEBUG + } else { + printf ("%px%d: %02x:%02x -> %02x:%02x\n", + caddr, portwidth, old[0], old[1], caddr[0], caddr[1]); +#endif + } + + switch (portwidth) { + case 1: + manu = caddr[0]; + manu |= manu << 16; + id = caddr[1]; + break; + case 2: + manu = saddr[0]; + manu |= manu << 16; + id = saddr[1]; + id |= id << 16; + break; + case 4: + manu = laddr[0]; + id = laddr[1]; + break; + } + +#ifdef DEBUG + flash_cmd (portwidth, caddr, 0, 0xf0); + + printf ("\n%08lx:%08lx:%08lx\n", base, manu, id); + printf ("%08lx %08lx %08lx %08lx\n", + laddr[0], laddr[1], laddr[2], laddr[3]); +#endif + + switch (manu) { + case STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + default: + flash_cmd (portwidth, caddr, 0, 0xf0); + + printf ("Unknown Mfr [%08lx]:%08lx\n", manu, id); + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + switch (id) { + case AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00100000; + info->chipwidth = 1; + break; /* => 1 MB */ + + case AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00100000; + info->chipwidth = 1; + break; /* => 1 MB */ + + case AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00200000; + info->chipwidth = 1; + break; /* => 2 MB */ + + case AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00200000; + info->chipwidth = 1; + break; /* => 2 MB */ + + case AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00400000; + info->chipwidth = 1; + break; /* => 4 MB */ + + case AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00400000; + info->chipwidth = 1; + break; /* => 4 MB */ +#if 0 /* enable when device IDs are available */ + case AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ + + case AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ +#endif + case AMD_ID_LV040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x80000; + info->chipwidth = 1; + break; /* => 512 kB */ + + case INTEL_ID_28F640J3A: + info->flash_id += FLASH_28F640J3A; + info->sector_count = 64; + info->size = 128 * 1024 * 64; /* 128kbytes x 64 blocks */ + info->chipwidth = 2; + if (portwidth == 4) + info->size *= 2; /* 2x16 */ + break; + + case INTEL_ID_28F128J3A: + info->flash_id += FLASH_28F128J3A; + info->sector_count = 128; + info->size = 128 * 1024 * 128; /* 128kbytes x 128 blocks */ + info->chipwidth = 2; + if (portwidth == 4) + info->size *= 2; /* 2x16 */ + break; + + default: + flash_cmd (portwidth, caddr, 0, 0xf0); + + printf ("Unknown id %lx:[%lx]\n", manu, id); + info->flash_id = FLASH_UNKNOWN; + info->chipwidth = 1; + return (0); /* => no or unknown flash */ + + } + + flash_get_offsets (base, info); + + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0)=0x02 */ + /* D0 = 1 if protected */ + caddr = (volatile unsigned char *) (info->start[i]); + saddr = (volatile unsigned short *) (info->start[i]); + laddr = (volatile unsigned long *) (info->start[i]); + if (portwidth == 1) + info->protect[i] = caddr[2] & 1; + else if (portwidth == 2) + info->protect[i] = saddr[2] & 1; + else + info->protect[i] = laddr[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + caddr = (volatile unsigned char *) info->start[0]; + + flash_cmd (portwidth, caddr, 0, 0xF0); /* reset bank */ + } + + return (info->size); +} + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + volatile unsigned char *addr = (char *) (info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + +/* modified to support 2x16 Intel flash */ +/* Note that the code will not exit on a flash erasure error or timeout */ +/* but will print and error message and continue processing sectors */ +/* until they are all erased. */ +/* 10-16-2002 P. Marchese */ + ulong mask; + int timeout; + + if (info->portwidth == 4) +/* { + printf ("- Warning: erasing of 32Bit (2*16Bit i.e. 2*28F640J3A) not supported yet !!!! \n"); + return 1; + }*/ + { + /* make sure it's Intel flash */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + /* yup! it's an Intel flash */ + /* is it 16-bits wide? */ + if (info->chipwidth == 2) { + /* yup! it's 16-bits wide */ + /* are there any sectors to process? */ + if ((s_first < 0) || (s_first > s_last)) { + printf ("Error: There are no sectors to erase\n"); + printf ("Either sector %d is less than zero\n", s_first); + printf ("or sector %d is greater than sector %d\n", s_first, s_last); + return 1; + } + /* check for protected sectors */ + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) + if (info->protect[sect]) + prot++; + /* if variable "prot" is nonzero, there are protected sectors */ + if (prot) + printf ("- Warning: %d protected sectors will not be erased!\n", prot); + /* reset the flash */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + /* Clear the status register */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_CLR_STAT); + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + /* is the sector unprotected? */ + if (info->protect[sect] == 0) { /* not protected */ + /* issue the single block erase command, 0x20 */ + flash_cmd (info->portwidth, + (volatile unsigned + char *) info-> + start[sect], 0, + CHIP_CMD_ERASE1); + /* issue the erase confirm command, 0xD0 */ + flash_cmd (info->portwidth, + (volatile unsigned + char *) info-> + start[sect], 0, + CHIP_CMD_ERASE2); + l_sect = sect; + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + /* poll for erasure completion */ + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, + addr, 0, + CHIP_CMD_RD_STAT); + /* setup the status register mask */ + mask = CHIP_STAT_RDY | + (CHIP_STAT_RDY << 16); + /* init. the timeout counter */ + start = get_timer (0); + /* keep looping while the flash is not ready */ + /* exit the loop by timing out or the flash */ + /* becomes ready again */ + timeout = 0; + while ((* + (volatile unsigned + long *) info-> + start[sect] & mask) != + mask) { + /* has the timeout limit been reached? */ + if (get_timer (start) + > + CFG_FLASH_ERASE_TOUT) + { + /* timeout limit reached */ + printf ("Time out limit reached erasing sector at address %08lx\n", info->start[sect]); + printf ("Continuing with next sector\n"); + timeout = 1; + goto timed_out_error; + } + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info-> + portwidth, + addr, 0, + CHIP_CMD_RD_STAT); + } + /* did we timeout? */ + timed_out_error:if (timeout == 0) + { + /* didn't timeout, so check the status register */ + /* create the status mask to check for errors */ + mask = CHIP_STAT_ECLBS; + mask = mask | (mask << + 16); + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info-> + portwidth, + addr, 0, + CHIP_CMD_RD_STAT); + /* are there any errors? */ + if ((* + (volatile + unsigned long *) + info-> + start[sect] & + mask) != 0) { + /* We got an erasure error */ + printf ("Flash erasure error at address 0x%08lx\n", info->start[sect]); + printf ("Continuing with next sector\n"); + /* reset the flash */ + flash_cmd + (info-> + portwidth, + addr, + 0, + CHIP_CMD_RST); + } + } + /* erasure completed without errors */ + /* reset the flash */ + flash_cmd (info->portwidth, + addr, 0, + CHIP_CMD_RST); + } /* end if not protected */ + } /* end for loop */ + printf ("Flash erasure done\n"); + return 0; + } else { + /* The Intel flash is not 16-bit wide */ + /* print and error message and return */ + /* NOTE: you can add routines here to handle other size flash */ + printf ("Error: Intel flash device is only %d-bits wide\n", info->chipwidth * 8); + printf ("The erasure code only handles Intel 16-bit wide flash memory\n"); + return 1; + } + } else { + /* Not Intel flash so return an error as a write timeout */ + /* NOTE: if it's another type flash, stick its routine here */ + printf ("Error: The flash device is not Intel type\n"); + printf ("The erasure code only supports Intel flash in a 32-bit port width\n"); + return 1; + } + } + + /* end 32-bit wide flash code */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) + return 1; /* Rom can not be erased */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) { /* RAM just copy 0s to RAM */ + for (sect = s_first; sect <= s_last; sect++) { + int sector_size = info->size / info->sector_count; + + addr = (char *) (info->start[sect]); + memset ((void *) addr, 0, sector_size); + } + return 0; + } + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { /* Intel works spezial */ + return flash_erase_intel (info, + (unsigned short) s_first, + (unsigned short) s_last); + } +#if 0 + if ((info->flash_id == FLASH_UNKNOWN) || /* Flash is unknown to PPCBoot */ + (info->flash_id > FLASH_AMD_COMP)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } +#endif + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + flash_cmd (info->portwidth, addr, 0x555, 0xAA); /* start erase routine */ + flash_cmd (info->portwidth, addr, 0x2AA, 0x55); + flash_cmd (info->portwidth, addr, 0x555, 0x80); + flash_cmd (info->portwidth, addr, 0x555, 0xAA); + flash_cmd (info->portwidth, addr, 0x2AA, 0x55); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (char *) (info->start[sect]); + flash_cmd (info->portwidth, addr, 0, 0x30); + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = (volatile unsigned char *) (info->start[l_sect]); + /* broken for 2x16: TODO */ + while ((addr[0] & 0x80) != 0x80) { + if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + + DONE: + /* reset to read mode */ + addr = (volatile unsigned char *) info->start[0]; + flash_cmd (info->portwidth, addr, 0, 0xf0); + flash_cmd (info->portwidth, addr, 0, 0xf0); + + printf (" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +/* broken for 2x16: TODO */ +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + +/* Commented out since the below code should work for 32-bit(2x 16 flash) */ +/* 10-16-2002 P. Marchese */ +/* if(info->portwidth==4) return 1; */ +/* if(info->portwidth==4) { + printf ("- Warning: writting of 32Bit (2*16Bit i.e. 2*28F640J3A) not supported yet !!!! \n"); + return 1; + }*/ + + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) + return 0; + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) { + memcpy ((void *) addr, src, cnt); + return 0; + } + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + for (; i < 4 && cnt > 0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt == 0 && i < 4; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + if ((rc = write_word (info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i = 0; i < 4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word (info, wp, data)) != 0) { + return (rc); + } + wp += 4; + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i < 4; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + return (write_word (info, wp, data)); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +/* broken for 2x16: TODO */ +static int write_word (flash_info_t * info, ulong dest, ulong data) +{ + volatile unsigned char *addr = (char *) (info->start[0]); + ulong start; + int flag, i; + ulong mask; + +/* modified so that it handles 32-bit(2x16 Intel flash programming */ +/* 10-16-2002 P. Marchese */ + + if (info->portwidth == 4) +/* { + printf ("- Warning: writting of 32Bit (2*16Bit i.e. 2*28F640J3A) not supported yet !!!! \n"); + return 1; + }*/ + { + /* make sure it's Intel flash */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + /* yup! it's an Intel flash */ + /* is it 16-bits wide? */ + if (info->chipwidth == 2) { + /* yup! it's 16-bits wide */ + /* so we know how to program it */ + /* reset the flash */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + /* Clear the status register */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_CLR_STAT); + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + /* 1st cycle of word/byte program */ + /* write 0x40 to the location to program */ + flash_cmd (info->portwidth, (char *) dest, 0, + CHIP_CMD_PROG); + /* 2nd cycle of word/byte program */ + /* write the data to the destination address */ + *(ulong *) dest = data; + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + /* setup the status register mask */ + mask = CHIP_STAT_RDY | (CHIP_STAT_RDY << 16); + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RD_STAT); + /* init. the timeout counter */ + start = get_timer (0); + /* keep looping while the flash is not ready */ + /* exit the loop by timing out or the flash */ + /* becomes ready again */ +/* 11-13-2002 Paul Marchese */ +/* modified while loop conditional statement */ +/* because we were always timing out. */ +/* there is a type mismatch, "addr[0]" */ +/* returns a byte but "mask" is a 32-bit value */ + while ((*(volatile unsigned long *) info-> + start[0] & mask) != mask) +/* original code */ +/* while (addr[0] & mask) != mask) */ + { + /* has the timeout limit been reached? */ + if (get_timer (start) > + CFG_FLASH_WRITE_TOUT) { + /* timeout limit reached */ + printf ("Time out limit reached programming address %08lx with data %08lx\n", dest, data); + /* reset the flash */ + flash_cmd (info->portwidth, + addr, 0, + CHIP_CMD_RST); + return (1); + } + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RD_STAT); + } + /* flash is ready, so check the status */ + /* create the status mask to check for errors */ + mask = CHIP_STAT_DPS | CHIP_STAT_VPPS | + CHIP_STAT_PSLBS; + mask = mask | (mask << 16); + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RD_STAT); + /* are there any errors? */ + if ((addr[0] & mask) != 0) { + /* We got a one of the following errors: */ + /* Voltage range, Device protect, or programming */ + /* return the error as a device timeout */ + /* put flash into read status mode by writing 0x70 to it */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RD_STAT); + printf ("Flash programming error at address 0x%08lx\n", dest); + printf ("Flash status register contains 0x%08lx\n", (unsigned long) addr[0]); + /* reset the flash */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + return 1; + } + /* write completed without errors */ + /* reset the flash */ + flash_cmd (info->portwidth, addr, 0, + CHIP_CMD_RST); + return 0; + } else { + /* it's not 16-bits wide, so return an error as a write timeout */ + /* NOTE: you can add routines here to handle other size flash */ + printf ("Error: Intel flash device is only %d-bits wide\n", info->chipwidth * 8); + printf ("The write code only handles Intel 16-bit wide flash memory\n"); + return 1; + } + } else { + /* not Intel flash so return an error as a write timeout */ + /* NOTE: if it's another type flash, stick its routine here */ + printf ("Error: The flash device is not Intel type\n"); + printf ("The code only supports Intel flash in a 32-bit port width\n"); + return 1; + } + } + + /* end of 32-bit flash code */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) + return 1; + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) { + *(unsigned long *) dest = data; + return 0; + } + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + unsigned short low = data & 0xffff; + unsigned short hi = (data >> 16) & 0xffff; + int ret = write_word_intel ((bank_addr_t) dest, hi); + + if (!ret) + ret = write_word_intel ((bank_addr_t) (dest + 2), + low); + + return ret; + } + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *) dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + /* first, perform an unlock bypass command to speed up flash writes */ + addr[0x555] = 0xAA; + addr[0x2AA] = 0x55; + addr[0x555] = 0x20; + + /* write each byte out */ + for (i = 0; i < 4; i++) { + char *data_ch = (char *) &data; + + addr[0] = 0xA0; + *(((char *) dest) + i) = data_ch[i]; + udelay (10); /* XXX */ + } + + /* we're done, now do an unlock bypass reset */ + addr[0] = 0x90; + addr[0] = 0x00; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + /* data polling for D7 */ + start = get_timer (0); + while ((*((vu_long *) dest) & 0x00800080) != (data & 0x00800080)) { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + return (0); +} diff --git a/board/Marvell/common/i2c.c b/board/Marvell/common/i2c.c new file mode 100644 index 0000000..624ee5c --- /dev/null +++ b/board/Marvell/common/i2c.c @@ -0,0 +1,532 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Hacked for the DB64360 board by Ingo.Assmus@keymile.com + * extra improvments by Brain Waite + */ +#include <common.h> +#include <mpc8xx.h> +#include <malloc.h> +#include "../include/mv_gen_reg.h" +#include "../include/core.h" + +#define MAX_I2C_RETRYS 10 +#define I2C_DELAY 1000 /* Should be at least the # of MHz of Tclk */ +#undef DEBUG_I2C +/*#define DEBUG_I2C*/ + +#ifdef DEBUG_I2C +#define DP(x) x +#else +#define DP(x) +#endif + +/* Assuming that there is only one master on the bus (us) */ + +static void i2c_init (int speed, int slaveaddr) +{ + unsigned int n, m, freq, margin, power; + unsigned int actualN = 0, actualM = 0; + unsigned int control, status; + unsigned int minMargin = 0xffffffff; + unsigned int tclk = CFG_TCLK; + unsigned int i2cFreq = speed; /* 100000 max. Fast mode not supported */ + + DP (puts ("i2c_init\n")); +/* gtI2cMasterInit */ + for (n = 0; n < 8; n++) { + for (m = 0; m < 16; m++) { + power = 2 << n; /* power = 2^(n+1) */ + freq = tclk / (10 * (m + 1) * power); + if (i2cFreq > freq) + margin = i2cFreq - freq; + else + margin = freq - i2cFreq; + if (margin < minMargin) { + minMargin = margin; + actualN = n; + actualM = m; + } + } + } + + DP (puts ("setup i2c bus\n")); + + /* Setup bus */ +/* gtI2cReset */ + GT_REG_WRITE (I2C_SOFT_RESET, 0); + + DP (puts ("udelay...\n")); + + udelay (I2C_DELAY); + + DP (puts ("set baudrate\n")); + + GT_REG_WRITE (I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN); + GT_REG_WRITE (I2C_CONTROL, (0x1 << 2) | (0x1 << 6)); + + udelay (I2C_DELAY * 10); + + DP (puts ("read control, baudrate\n")); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + GT_REG_READ (I2C_CONTROL, &control); +} + +static uchar i2c_start (void) +{ /* DB64360 checked -> ok */ + unsigned int control, status; + int count = 0; + + DP (puts ("i2c_start\n")); + + /* Set the start bit */ + +/* gtI2cGenerateStartBit() */ + + GT_REG_READ (I2C_CONTROL, &control); + control |= (0x1 << 5); /* generate the I2C_START_BIT */ + GT_REG_WRITE (I2C_CONTROL, control); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + + count = 0; + while ((status & 0xff) != 0x08) { + udelay (I2C_DELAY); + if (count > 20) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + + return (0); +} + +static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit) +{ + unsigned int status, data, bits = 7; + int count = 0; + + DP (puts ("i2c_select_device\n")); + + /* Output slave address */ + + if (ten_bit) { + bits = 10; + } + + data = (dev_addr << 1); + /* set the read bit */ + data |= read; + GT_REG_WRITE (I2C_DATA, data); + /* assert the address */ + RESET_REG_BITS (I2C_CONTROL, BIT3); + + udelay (I2C_DELAY); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count = 0; + while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) { + udelay (I2C_DELAY); + if (count > 20) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + + if (bits == 10) { + printf ("10 bit I2C addressing not yet implemented\n"); + return (0xff); + } + + return (0); +} + +static uchar i2c_get_data (uchar * return_data, int len) +{ + + unsigned int data, status; + int count = 0; + + DP (puts ("i2c_get_data\n")); + + while (len) { + + /* Get and return the data */ + + RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); + + udelay (I2C_DELAY * 5); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + while ((status & 0xff) != 0x50) { + udelay (I2C_DELAY); + if (count > 2) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return 0; + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + GT_REG_READ (I2C_DATA, &data); + len--; + *return_data = (uchar) data; + return_data++; + } + RESET_REG_BITS (I2C_CONTROL, BIT2 | BIT3); + while ((status & 0xff) != 0x58) { + udelay (I2C_DELAY); + if (count > 200) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /* stop */ + + return (0); +} + +static uchar i2c_write_data (unsigned int *data, int len) +{ + unsigned int status; + int count = 0; + unsigned int temp; + unsigned int *temp_ptr = data; + + DP (puts ("i2c_write_data\n")); + + while (len) { + temp = (unsigned int) (*temp_ptr); + GT_REG_WRITE (I2C_DATA, temp); + RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); + + udelay (I2C_DELAY); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + while ((status & 0xff) != 0x28) { + udelay (I2C_DELAY); + if (count > 20) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + len--; + temp_ptr++; + } +/* 11-14-2002 Paul Marchese */ +/* Can't have the write issuing a stop command */ +/* it's wrong to have a stop bit in read stream or write stream */ +/* since we don't know if it's really the end of the command */ +/* or whether we have just send the device address + offset */ +/* we will push issuing the stop command off to the original */ +/* calling function */ + /* set the interrupt bit in the control register */ + GT_REG_WRITE (I2C_CONTROL, (0x1 << 3)); + udelay (I2C_DELAY * 10); + return (0); +} + +/* 11-14-2002 Paul Marchese */ +/* created this function to get the i2c_write() */ +/* function working properly. */ +/* function to write bytes out on the i2c bus */ +/* this is identical to the function i2c_write_data() */ +/* except that it requires a buffer that is an */ +/* unsigned character array. You can't use */ +/* i2c_write_data() to send an array of unsigned characters */ +/* since the byte of interest ends up on the wrong end of the bus */ +/* aah, the joys of big endian versus little endian! */ +/* */ +/* returns 0 = success */ +/* anything other than zero is failure */ +static uchar i2c_write_byte (unsigned char *data, int len) +{ + unsigned int status; + int count = 0; + unsigned int temp; + unsigned char *temp_ptr = data; + + DP (puts ("i2c_write_byte\n")); + + while (len) { + /* Set and assert the data */ + temp = *temp_ptr; + GT_REG_WRITE (I2C_DATA, temp); + RESET_REG_BITS (I2C_CONTROL, (0x1 << 3)); + + udelay (I2C_DELAY); + + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + while ((status & 0xff) != 0x28) { + udelay (I2C_DELAY); + if (count > 20) { + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */ + return (status); + } + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status); + count++; + } + len--; + temp_ptr++; + } +/* Can't have the write issuing a stop command */ +/* it's wrong to have a stop bit in read stream or write stream */ +/* since we don't know if it's really the end of the command */ +/* or whether we have just send the device address + offset */ +/* we will push issuing the stop command off to the original */ +/* calling function */ +/* GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4)); + GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); */ + /* set the interrupt bit in the control register */ + GT_REG_WRITE (I2C_CONTROL, (0x1 << 3)); + udelay (I2C_DELAY * 10); + + return (0); +} + +static uchar +i2c_set_dev_offset (uchar dev_addr, unsigned int offset, int ten_bit, + int alen) +{ + uchar status; + unsigned int table[2]; + +/* initialize the table of address offset bytes */ +/* utilized for 2 byte address offsets */ +/* NOTE: the order is high byte first! */ + table[1] = offset & 0xff; /* low byte */ + table[0] = offset / 0x100; /* high byte */ + + DP (puts ("i2c_set_dev_offset\n")); + + status = i2c_select_device (dev_addr, 0, ten_bit); + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to select device setting offset: 0x%02x\n", + status); +#endif + return status; + } +/* check the address offset length */ + if (alen == 0) + /* no address offset */ + return (0); + else if (alen == 1) { + /* 1 byte address offset */ + status = i2c_write_data (&offset, 1); + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to write data: 0x%02x\n", status); +#endif + return status; + } + } else if (alen == 2) { + /* 2 bytes address offset */ + status = i2c_write_data (table, 2); + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to write data: 0x%02x\n", status); +#endif + return status; + } + } else { + /* address offset unknown or not supported */ + printf ("Address length offset %d is not supported\n", alen); + return 1; + } + return 0; /* sucessful completion */ +} + +uchar +i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data, + int len) +{ + uchar status = 0; + unsigned int i2cFreq = CFG_I2C_SPEED; + + DP (puts ("i2c_read\n")); + + i2c_init (i2cFreq, 0); /* set the i2c frequency */ + + status = i2c_start (); + + if (status) { +#ifdef DEBUG_I2C + printf ("Transaction start failed: 0x%02x\n", status); +#endif + return status; + } + + status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */ + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to set slave address & offset: 0x%02x\n", + status); +#endif + return status; + } + + i2c_init (i2cFreq, 0); /* set the i2c frequency again */ + + status = i2c_start (); + if (status) { +#ifdef DEBUG_I2C + printf ("Transaction restart failed: 0x%02x\n", status); +#endif + return status; + } + + status = i2c_select_device (dev_addr, 1, 0); /* send the slave address */ + if (status) { +#ifdef DEBUG_I2C + printf ("Address not acknowledged: 0x%02x\n", status); +#endif + return status; + } + + status = i2c_get_data (data, len); + if (status) { +#ifdef DEBUG_I2C + printf ("Data not recieved: 0x%02x\n", status); +#endif + return status; + } + + return 0; +} + +/* 11-14-2002 Paul Marchese */ +/* Function to set the I2C stop bit */ +void i2c_stop (void) +{ + GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); +} + +/* 11-14-2002 Paul Marchese */ +/* I2C write function */ +/* dev_addr = device address */ +/* offset = address offset */ +/* alen = length in bytes of the address offset */ +/* data = pointer to buffer to read data into */ +/* len = # of bytes to read */ +/* */ +/* returns 0 = succesful */ +/* anything but zero is failure */ +uchar +i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data, + int len) +{ + uchar status = 0; + unsigned int i2cFreq = CFG_I2C_SPEED; + + DP (puts ("i2c_write\n")); + + i2c_init (i2cFreq, 0); /* set the i2c frequency */ + + status = i2c_start (); /* send a start bit */ + + if (status) { +#ifdef DEBUG_I2C + printf ("Transaction start failed: 0x%02x\n", status); +#endif + return status; + } + + status = i2c_set_dev_offset (dev_addr, offset, 0, alen); /* send the slave address + offset */ + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to set slave address & offset: 0x%02x\n", + status); +#endif + return status; + } + + + status = i2c_write_byte (data, len); /* write the data */ + if (status) { +#ifdef DEBUG_I2C + printf ("Data not written: 0x%02x\n", status); +#endif + return status; + } + /* issue a stop bit */ + i2c_stop (); + return 0; +} + +/* 11-14-2002 Paul Marchese */ +/* function to determine if an I2C device is present */ +/* chip = device address of chip to check for */ +/* */ +/* returns 0 = sucessful, the device exists */ +/* anything other than zero is failure, no device */ +int i2c_probe (uchar chip) +{ + + /* We are just looking for an <ACK> back. */ + /* To see if the device/chip is there */ + +#ifdef DEBUG_I2C + unsigned int i2c_status; +#endif + uchar status = 0; + unsigned int i2cFreq = CFG_I2C_SPEED; + + DP (puts ("i2c_probe\n")); + + i2c_init (i2cFreq, 0); /* set the i2c frequency */ + + status = i2c_start (); /* send a start bit */ + + if (status) { +#ifdef DEBUG_I2C + printf ("Transaction start failed: 0x%02x\n", status); +#endif + return (int) status; + } + + status = i2c_set_dev_offset (chip, 0, 0, 0); /* send the slave address + no offset */ + if (status) { +#ifdef DEBUG_I2C + printf ("Failed to set slave address: 0x%02x\n", status); +#endif + return (int) status; + } +#ifdef DEBUG_I2C + GT_REG_READ (I2C_STATUS_BAUDE_RATE, &i2c_status); + printf ("address %#x returned %#x\n", chip, i2c_status); +#endif + /* issue a stop bit */ + i2c_stop (); + return 0; /* successful completion */ +} diff --git a/board/Marvell/common/i2c.h b/board/Marvell/common/i2c.h new file mode 100644 index 0000000..b669ff0 --- /dev/null +++ b/board/Marvell/common/i2c.h @@ -0,0 +1,32 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Hacked for the DB64360 board by Ingo.Assmus@keymile.com + */ + +#ifndef __I2C_H__ +#define __I2C_H__ + +/* function declarations */ +uchar i2c_read(uchar, unsigned int, int, uchar*, int); + +#endif diff --git a/board/Marvell/common/intel_flash.c b/board/Marvell/common/intel_flash.c new file mode 100644 index 0000000..d26f883 --- /dev/null +++ b/board/Marvell/common/intel_flash.c @@ -0,0 +1,269 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Hacked for the marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + */ + +#include <common.h> +#include <mpc8xx.h> +#include "../include/mv_gen_reg.h" +#include "../include/memory.h" +#include "intel_flash.h" + + +/*----------------------------------------------------------------------- + * Protection Flags: + */ +#define FLAG_PROTECT_SET 0x01 +#define FLAG_PROTECT_CLEAR 0x02 + +static void bank_reset (flash_info_t * info, int sect) +{ + bank_addr_t addrw, eaddrw; + + addrw = (bank_addr_t) info->start[sect]; + eaddrw = BANK_ADDR_NEXT_WORD (addrw); + + while (addrw < eaddrw) { +#ifdef FLASH_DEBUG + printf (" writing reset cmd to addr 0x%08lx\n", + (unsigned long) addrw); +#endif + *addrw = BANK_CMD_RST; + addrw++; + } +} + +static void bank_erase_init (flash_info_t * info, int sect) +{ + bank_addr_t addrw, saddrw, eaddrw; + int flag; + +#ifdef FLASH_DEBUG + printf ("0x%08x BANK_CMD_PROG\n", BANK_CMD_PROG); + printf ("0x%08x BANK_CMD_ERASE1\n", BANK_CMD_ERASE1); + printf ("0x%08x BANK_CMD_ERASE2\n", BANK_CMD_ERASE2); + printf ("0x%08x BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT); + printf ("0x%08x BANK_CMD_RST\n", BANK_CMD_RST); + printf ("0x%08x BANK_STAT_RDY\n", BANK_STAT_RDY); + printf ("0x%08x BANK_STAT_ERR\n", BANK_STAT_ERR); +#endif + + saddrw = (bank_addr_t) info->start[sect]; + eaddrw = BANK_ADDR_NEXT_WORD (saddrw); + +#ifdef FLASH_DEBUG + printf ("erasing sector %d, start addr = 0x%08lx " + "(bank next word addr = 0x%08lx)\n", sect, + (unsigned long) saddrw, (unsigned long) eaddrw); +#endif + + /* Disable intrs which might cause a timeout here */ + flag = disable_interrupts (); + + for (addrw = saddrw; addrw < eaddrw; addrw++) { +#ifdef FLASH_DEBUG + printf (" writing erase cmd to addr 0x%08lx\n", + (unsigned long) addrw); +#endif + *addrw = BANK_CMD_ERASE1; + *addrw = BANK_CMD_ERASE2; + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); +} + +static int bank_erase_poll (flash_info_t * info, int sect) +{ + bank_addr_t addrw, saddrw, eaddrw; + int sectdone, haderr; + + saddrw = (bank_addr_t) info->start[sect]; + eaddrw = BANK_ADDR_NEXT_WORD (saddrw); + + sectdone = 1; + haderr = 0; + + for (addrw = saddrw; addrw < eaddrw; addrw++) { + bank_word_t stat = *addrw; + +#ifdef FLASH_DEBUG + printf (" checking status at addr " + "0x%08x [0x%08x]\n", (unsigned long) addrw, stat); +#endif + if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY) + sectdone = 0; + else if ((stat & BANK_STAT_ERR) != 0) { + printf (" failed on sector %d " + "(stat = 0x%08x) at " + "address 0x%p\n", sect, stat, addrw); + *addrw = BANK_CMD_CLR_STAT; + haderr = 1; + } + } + + if (haderr) + return (-1); + else + return (sectdone); +} + +int write_word_intel (bank_addr_t addr, bank_word_t value) +{ + bank_word_t stat; + ulong start; + int flag, retval; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + *addr = BANK_CMD_PROG; + + *addr = value; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts (); + + retval = 0; + + /* data polling for D7 */ + start = get_timer (0); + do { + if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { + retval = 1; + goto done; + } + stat = *addr; + } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY); + + if ((stat & BANK_STAT_ERR) != 0) { + printf ("flash program failed (stat = 0x%08lx) " + "at address 0x%08lx\n", (ulong) stat, (ulong) addr); + *addr = BANK_CMD_CLR_STAT; + retval = 3; + } + + done: + /* reset to read mode */ + *addr = BANK_CMD_RST; + + return (retval); +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase_intel (flash_info_t * info, int s_first, int s_last) +{ + int prot, sect, haderr; + ulong start, now, last; + +#ifdef FLASH_DEBUG + printf ("\nflash_erase: erase %d sectors (%d to %d incl.) from\n" + " Bank # %d: ", s_last - s_first + 1, s_first, s_last, + (info - flash_info) + 1); + flash_print_info (info); +#endif + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sector%s will not be erased!\n", prot, (prot > 1 ? "s" : "")); + } + + start = get_timer (0); + last = 0; + haderr = 0; + + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + ulong estart; + int sectdone; + + bank_erase_init (info, sect); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + estart = get_timer (start); + + do { + now = get_timer (start); + + if (now - estart > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout (sect %d)\n", sect); + haderr = 1; + break; + } +#ifndef FLASH_DEBUG + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } +#endif + + sectdone = bank_erase_poll (info, sect); + + if (sectdone < 0) { + haderr = 1; + break; + } + + } while (!sectdone); + + if (haderr) + break; + } + } + + if (haderr > 0) + printf (" failed\n"); + else + printf (" done\n"); + + /* reset to read mode */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + bank_reset (info, sect); + } + } + return haderr; +} diff --git a/board/Marvell/common/intel_flash.h b/board/Marvell/common/intel_flash.h new file mode 100644 index 0000000..666a4cd --- /dev/null +++ b/board/Marvell/common/intel_flash.h @@ -0,0 +1,186 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Hacked for the marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + */ + +/*************** DEFINES for Intel StrataFlash FLASH chip ********************/ + +/* + * acceptable chips types are: + * + * 28F320J5, 28F640J5, 28F320J3A, 28F640J3A and 28F128J3A + */ + +/* register addresses, valid only following an CHIP_CMD_RD_ID command */ +#define CHIP_ADDR_REG_MAN 0x000000 /* manufacturer's id */ +#define CHIP_ADDR_REG_DEV 0x000001 /* device id */ +#define CHIP_ADDR_REG_CFGM 0x000003 /* master lock config */ +#define CHIP_ADDR_REG_CFG(b) (((b)<<16)|2) /* lock config for block b */ + +/* Commands */ +#define CHIP_CMD_RST 0xFF /* reset flash */ +#define CHIP_CMD_RD_ID 0x90 /* read the id and lock bits */ +#define CHIP_CMD_RD_QUERY 0x98 /* read device capabilities */ +#define CHIP_CMD_RD_STAT 0x70 /* read the status register */ +#define CHIP_CMD_CLR_STAT 0x50 /* clear the staus register */ +#define CHIP_CMD_WR_BUF 0xE8 /* clear the staus register */ +#define CHIP_CMD_PROG 0x40 /* program word command */ +#define CHIP_CMD_ERASE1 0x20 /* 1st word for block erase */ +#define CHIP_CMD_ERASE2 0xD0 /* 2nd word for block erase */ +#define CHIP_CMD_ERASE_SUSP 0xB0 /* suspend block erase */ +#define CHIP_CMD_LOCK 0x60 /* 1st word for all lock cmds */ +#define CHIP_CMD_SET_LOCK_BLK 0x01 /* 2nd wrd set block lock bit */ +#define CHIP_CMD_SET_LOCK_MSTR 0xF1 /* 2nd wrd set master lck bit */ +#define CHIP_CMD_CLR_LOCK_BLK 0xD0 /* 2nd wrd clear blk lck bit */ + +/* status register bits */ +#define CHIP_STAT_DPS 0x02 /* Device Protect Status */ +#define CHIP_STAT_VPPS 0x08 /* VPP Status */ +#define CHIP_STAT_PSLBS 0x10 /* Program+Set Lock Bit Stat */ +#define CHIP_STAT_ECLBS 0x20 /* Erase+Clr Lock Bit Stat */ +#define CHIP_STAT_ESS 0x40 /* Erase Suspend Status */ +#define CHIP_STAT_RDY 0x80 /* WSM Mach Status, 1=rdy */ + +#define CHIP_STAT_ERR (CHIP_STAT_VPPS | CHIP_STAT_DPS | \ + CHIP_STAT_ECLBS | CHIP_STAT_PSLBS) + +/* ID and Lock Configuration */ +#define CHIP_RD_ID_LOCK 0x01 /* Bit 0 of each byte */ +#define CHIP_RD_ID_MAN 0x89 /* Manufacturer code = 0x89 */ +#define CHIP_RD_ID_DEV CFG_FLASH_ID + +/* dimensions */ +#define CHIP_WIDTH 2 /* chips are in 16 bit mode */ +#define CHIP_WSHIFT 1 /* (log2 of CHIP_WIDTH) */ +#define CHIP_NBLOCKS 128 +#define CHIP_BLKSZ (128 * 1024) /* of 128Kbytes each */ +#define CHIP_SIZE (CHIP_BLKSZ * CHIP_NBLOCKS) + +/********************** DEFINES for Hymod Flash ******************************/ + +/* + * The hymod board has 2 x 28F320J5 chips running in + * 16 bit mode, for a 32 bit wide bank. + */ + +typedef unsigned short bank_word_t; /* 8/16/32/64bit unsigned int */ +typedef volatile bank_word_t *bank_addr_t; +typedef unsigned long bank_size_t; /* want this big - >= 32 bit */ + +#define BANK_CHIP_WIDTH 1 /* each bank is 1 chip wide */ +#define BANK_CHIP_WSHIFT 0 /* (log2 of BANK_CHIP_WIDTH) */ + +#define BANK_WIDTH (CHIP_WIDTH * BANK_CHIP_WIDTH) +#define BANK_WSHIFT (CHIP_WSHIFT + BANK_CHIP_WSHIFT) +#define BANK_NBLOCKS CHIP_NBLOCKS +#define BANK_BLKSZ (CHIP_BLKSZ * BANK_CHIP_WIDTH) +#define BANK_SIZE (CHIP_SIZE * BANK_CHIP_WIDTH) + +#define MAX_BANKS 1 /* only one bank possible */ + +/* align bank addresses and sizes to bank word boundaries */ +#define BANK_ADDR_WORD_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \ + & ~(BANK_WIDTH - 1))) +#define BANK_SIZE_WORD_ALIGN(s) ((bank_size_t)BANK_ADDR_WORD_ALIGN( \ + (bank_size_t)(s) + (BANK_WIDTH - 1))) + +/* align bank addresses and sizes to bank block boundaries */ +#define BANK_ADDR_BLK_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \ + & ~(BANK_BLKSZ - 1))) +#define BANK_SIZE_BLK_ALIGN(s) ((bank_size_t)BANK_ADDR_BLK_ALIGN( \ + (bank_size_t)(s) + (BANK_BLKSZ - 1))) + +/* align bank addresses and sizes to bank boundaries */ +#define BANK_ADDR_BANK_ALIGN(a) ((bank_addr_t)((bank_size_t)(a) \ + & ~(BANK_SIZE - 1))) +#define BANK_SIZE_BANK_ALIGN(s) ((bank_size_t)BANK_ADDR_BANK_ALIGN( \ + (bank_size_t)(s) + (BANK_SIZE - 1))) + +/* add an offset to a bank address */ +#define BANK_ADDR_OFFSET(a, o) (bank_addr_t)((bank_size_t)(a) + \ + (bank_size_t)(o)) + +/* get base address of bank b, given flash base address a */ +#define BANK_ADDR_BASE(a, b) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \ + (bank_size_t)(b) * BANK_SIZE) + +/* adjust a bank address to start of next word, block or bank */ +#define BANK_ADDR_NEXT_WORD(a) BANK_ADDR_OFFSET(BANK_ADDR_WORD_ALIGN(a), \ + BANK_WIDTH) +#define BANK_ADDR_NEXT_BLK(a) BANK_ADDR_OFFSET(BANK_ADDR_BLK_ALIGN(a), \ + BANK_BLKSZ) +#define BANK_ADDR_NEXT_BANK(a) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \ + BANK_SIZE) + +/* get bank address of chip register r given a bank base address a */ +#define BANK_ADDR_REG(a, r) BANK_ADDR_OFFSET(BANK_ADDR_BANK_ALIGN(a), \ + ((bank_size_t)(r) << BANK_WSHIFT)) + +/* make a bank address for each chip register address */ + +#define BANK_ADDR_REG_MAN(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_MAN) +#define BANK_ADDR_REG_DEV(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_DEV) +#define BANK_ADDR_REG_CFGM(a) BANK_ADDR_REG((a), CHIP_ADDR_REG_CFGM) +#define BANK_ADDR_REG_CFG(b,a) BANK_ADDR_REG((a), CHIP_ADDR_REG_CFG(b)) + +/* + * replicate a chip cmd/stat/rd value into each byte position within a word + * so that multiple chips are accessed in a single word i/o operation + * + * this must be as wide as the bank_word_t type, and take into account the + * chip width and bank layout + */ + +#define BANK_FILL_WORD(o) ((bank_word_t)(o)) + +/* make a bank word value for each chip cmd/stat/rd value */ + +/* Commands */ +#define BANK_CMD_RST BANK_FILL_WORD(CHIP_CMD_RST) +#define BANK_CMD_RD_ID BANK_FILL_WORD(CHIP_CMD_RD_ID) +#define BANK_CMD_RD_STAT BANK_FILL_WORD(CHIP_CMD_RD_STAT) +#define BANK_CMD_CLR_STAT BANK_FILL_WORD(CHIP_CMD_CLR_STAT) +#define BANK_CMD_ERASE1 BANK_FILL_WORD(CHIP_CMD_ERASE1) +#define BANK_CMD_ERASE2 BANK_FILL_WORD(CHIP_CMD_ERASE2) +#define BANK_CMD_PROG BANK_FILL_WORD(CHIP_CMD_PROG) +#define BANK_CMD_LOCK BANK_FILL_WORD(CHIP_CMD_LOCK) +#define BANK_CMD_SET_LOCK_BLK BANK_FILL_WORD(CHIP_CMD_SET_LOCK_BLK) +#define BANK_CMD_SET_LOCK_MSTR BANK_FILL_WORD(CHIP_CMD_SET_LOCK_MSTR) +#define BANK_CMD_CLR_LOCK_BLK BANK_FILL_WORD(CHIP_CMD_CLR_LOCK_BLK) + +/* status register bits */ +#define BANK_STAT_DPS BANK_FILL_WORD(CHIP_STAT_DPS) +#define BANK_STAT_PSS BANK_FILL_WORD(CHIP_STAT_PSS) +#define BANK_STAT_VPPS BANK_FILL_WORD(CHIP_STAT_VPPS) +#define BANK_STAT_PSLBS BANK_FILL_WORD(CHIP_STAT_PSLBS) +#define BANK_STAT_ECLBS BANK_FILL_WORD(CHIP_STAT_ECLBS) +#define BANK_STAT_ESS BANK_FILL_WORD(CHIP_STAT_ESS) +#define BANK_STAT_RDY BANK_FILL_WORD(CHIP_STAT_RDY) + +#define BANK_STAT_ERR BANK_FILL_WORD(CHIP_STAT_ERR) + +/* ID and Lock Configuration */ +#define BANK_RD_ID_LOCK BANK_FILL_WORD(CHIP_RD_ID_LOCK) +#define BANK_RD_ID_MAN BANK_FILL_WORD(CHIP_RD_ID_MAN) +#define BANK_RD_ID_DEV BANK_FILL_WORD(CHIP_RD_ID_DEV) diff --git a/board/Marvell/common/memory.c b/board/Marvell/common/memory.c new file mode 100644 index 0000000..45353af --- /dev/null +++ b/board/Marvell/common/memory.c @@ -0,0 +1,1390 @@ +/* + * Copyright - Galileo technology. + * + * 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 + */ + +/* + * + * written or collected and sometimes rewritten by + * Ingo Assmus <ingo.assmus@keymile.com> + * + */ + + +#include <common.h> +#include "../include/core.h" +#include "../include/memory.h" + +/******************************************************************************* +* memoryGetBankBaseAddress - Returns the base address of a memory bank. +* DESCRIPTION: +* This function returns the base address of one of the SDRAM’s memory +* banks. There are 4 memory banks and each one represents one DIMM side. +* INPUT: +* MEMORY_BANK bank - Selects one of the four banks as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit Memory bank base address. +*******************************************************************************/ +static unsigned long memoryGetBankRegOffset (MEMORY_BANK bank) +{ + switch (bank) { + case BANK0: + return SCS_0_LOW_DECODE_ADDRESS; + case BANK1: + return SCS_1_LOW_DECODE_ADDRESS; + case BANK2: + return SCS_2_LOW_DECODE_ADDRESS; + case BANK3: + return SCS_3_LOW_DECODE_ADDRESS; + + } + return SCS_0_LOW_DECODE_ADDRESS; /* default value */ +} + +unsigned int memoryGetBankBaseAddress (MEMORY_BANK bank) +{ + unsigned int base; + unsigned int regOffset = memoryGetBankRegOffset (bank); + + GT_REG_READ (regOffset, &base); + base = base << 16; /* MV6436x */ + return base; +} + +/******************************************************************************* +* memoryGetDeviceBaseAddress - Returns the base address of a device. +* DESCRIPTION: +* This function returns the base address of a device on the system. There +* are 5 possible devices (0 - 4 and one boot device) as defined in +* gtMemory.h. Each of the device parameters is maped to one of the CS +* (Devices chip selects) base address register. +* INPUT: +* device - Selects one of the five devices as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit Device base address. +* +*******************************************************************************/ +static unsigned int memoryGetDeviceRegOffset (DEVICE device) +{ + switch (device) { + case DEVICE0: + return CS_0_LOW_DECODE_ADDRESS; + case DEVICE1: + return CS_1_LOW_DECODE_ADDRESS; + case DEVICE2: + return CS_2_LOW_DECODE_ADDRESS; + case DEVICE3: + return CS_3_LOW_DECODE_ADDRESS; + case BOOT_DEVICE: + return BOOTCS_LOW_DECODE_ADDRESS; + } + return CS_0_LOW_DECODE_ADDRESS; /* default value */ +} + +unsigned int memoryGetDeviceBaseAddress (DEVICE device) +{ + unsigned int regBase; + unsigned int regOffset = memoryGetDeviceRegOffset (device); + + GT_REG_READ (regOffset, ®Base); + + regBase = regBase << 16; /* MV6436x */ + return regBase; +} + +/******************************************************************************* +* MemoryGetPciBaseAddr - Returns the base address of a PCI window. +* DESCRIPTION: +* This function returns the base address of a PCI window. There are 5 +* possible PCI windows (memory 0 - 3 and one for I/O) for each PCI +* interface as defined in gtMemory.h, used by the CPU's address decoding +* mechanism. +* New in MV6436x +* INPUT: +* pciWindow - Selects one of the PCI windows as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit PCI window base address. +*******************************************************************************/ +unsigned int MemoryGetPciBaseAddr (PCI_MEM_WINDOW pciWindow) +{ + unsigned int baseAddrReg, base; + + switch (pciWindow) { + case PCI_0_IO: + baseAddrReg = PCI_0I_O_LOW_DECODE_ADDRESS; /*PCI_0_IO_BASE_ADDR; */ + break; + case PCI_0_MEM0: + baseAddrReg = PCI_0MEMORY0_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY0_BASE_ADDR; */ + break; + case PCI_0_MEM1: + baseAddrReg = PCI_0MEMORY1_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY1_BASE_ADDR; */ + break; + case PCI_0_MEM2: + baseAddrReg = PCI_0MEMORY2_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY2_BASE_ADDR; */ + break; + case PCI_0_MEM3: + baseAddrReg = PCI_0MEMORY3_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY3_BASE_ADDR; */ + break; +#ifdef INCLUDE_PCI_1 + case PCI_1_IO: + baseAddrReg = PCI_1I_O_LOW_DECODE_ADDRESS; /*PCI_1_IO_BASE_ADDR; */ + break; + case PCI_1_MEM0: + baseAddrReg = PCI_1MEMORY0_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY0_BASE_ADDR; */ + break; + case PCI_1_MEM1: + baseAddrReg = PCI_1MEMORY1_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY1_BASE_ADDR; */ + break; + case PCI_1_MEM2: + baseAddrReg = PCI_1MEMORY2_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY2_BASE_ADDR; */ + break; + case PCI_1_MEM3: + baseAddrReg = PCI_1MEMORY3_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY3_BASE_ADDR; */ + break; +#endif /* INCLUDE_PCI_1 */ + default: + return 0xffffffff; + } + GT_REG_READ (baseAddrReg, &base); + return (base << 16); +} + +/******************************************************************************* +* memoryGetBankSize - Returns the size of a memory bank. +* DESCRIPTION: +* This function returns the size of memory bank as described in +* 'gtMemoryGetBankBaseAddress' function. +* INPUT: +* bank - Selects one of the four banks as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit size memory bank size or 0 for a closed or non populated bank. +* +*******************************************************************************/ +unsigned int memoryGetBankSize (MEMORY_BANK bank) +{ + unsigned int sizeReg, size; + MEMORY_WINDOW window; + + switch (bank) { + case BANK0: + sizeReg = SCS_0_HIGH_DECODE_ADDRESS; /* CS_0_SIZE; */ + window = CS_0_WINDOW; + break; + case BANK1: + sizeReg = SCS_1_HIGH_DECODE_ADDRESS; /* CS_1_SIZE; */ + window = CS_1_WINDOW; + break; + case BANK2: + sizeReg = SCS_2_HIGH_DECODE_ADDRESS; /* CS_2_SIZE; */ + window = CS_2_WINDOW; + break; + case BANK3: + sizeReg = SCS_3_HIGH_DECODE_ADDRESS; /* CS_3_SIZE; */ + window = CS_3_WINDOW; + break; + default: + return 0; + break; + } + /* If the window is closed, a size of 0 is returned */ + if (MemoryGetMemWindowStatus (window) != MEM_WINDOW_ENABLED) + return 0; + GT_REG_READ (sizeReg, &size); + size = ((size << 16) | 0xffff) + 1; + return size; +} + +/******************************************************************************* +* memoryGetDeviceSize - Returns the size of a device memory space. +* DESCRIPTION: +* This function returns the memory space size of a given device. +* INPUT: +* device - Selects one of the five devices as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit size of a device memory space. +*******************************************************************************/ +unsigned int memoryGetDeviceSize (DEVICE device) +{ + unsigned int sizeReg, size; + MEMORY_WINDOW window; + + switch (device) { + case DEVICE0: + sizeReg = CS_0_HIGH_DECODE_ADDRESS; /*DEV_CS0_SIZE; */ + window = DEVCS_0_WINDOW; + break; + case DEVICE1: + sizeReg = CS_1_HIGH_DECODE_ADDRESS; /*DEV_CS1_SIZE; */ + window = DEVCS_1_WINDOW; + break; + case DEVICE2: + sizeReg = CS_2_HIGH_DECODE_ADDRESS; /*DEV_CS2_SIZE; */ + window = DEVCS_2_WINDOW; + break; + case DEVICE3: + sizeReg = CS_3_HIGH_DECODE_ADDRESS; /*DEV_CS3_SIZE; */ + window = DEVCS_3_WINDOW; + break; + case BOOT_DEVICE: + sizeReg = BOOTCS_HIGH_DECODE_ADDRESS; /*BOOTCS_SIZE; */ + window = BOOT_CS_WINDOW; + break; + default: + return 0; + break; + } + /* If the window is closed, a size of 0 is returned */ + if (MemoryGetMemWindowStatus (window) != MEM_WINDOW_ENABLED) + return 0; + GT_REG_READ (sizeReg, &size); + size = ((size << 16) | 0xffff) + 1; + return size; +} + +/******************************************************************************* +* MemoryGetPciWindowSize - Returns the size of a PCI memory window. +* DESCRIPTION: +* This function returns the size of a PCI window. +* INPUT: +* pciWindow - Selects one of the PCI memory windows as defined in +* Memory.h. +* OUTPUT: +* None. +* RETURN: +* 32 bit size of a PCI memory window. +*******************************************************************************/ +unsigned int MemoryGetPciWindowSize (PCI_MEM_WINDOW pciWindow) +{ + unsigned int sizeReg, size; + + switch (pciWindow) { + case PCI_0_IO: + sizeReg = PCI_0I_O_HIGH_DECODE_ADDRESS; /*PCI_0_IO_SIZE; */ + break; + case PCI_0_MEM0: + sizeReg = PCI_0MEMORY0_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY0_SIZE; */ + break; + case PCI_0_MEM1: + sizeReg = PCI_0MEMORY1_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY1_SIZE; */ + break; + case PCI_0_MEM2: + sizeReg = PCI_0MEMORY2_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY2_SIZE; */ + break; + case PCI_0_MEM3: + sizeReg = PCI_0MEMORY3_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY3_SIZE; */ + break; +#ifdef INCLUDE_PCI_1 + case PCI_1_IO: + sizeReg = PCI_1I_O_HIGH_DECODE_ADDRESS; /*PCI_1_IO_SIZE; */ + break; + case PCI_1_MEM0: + sizeReg = PCI_1MEMORY0_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY0_SIZE; */ + break; + case PCI_1_MEM1: + sizeReg = PCI_1MEMORY1_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY1_SIZE; */ + break; + case PCI_1_MEM2: + sizeReg = PCI_1MEMORY2_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY2_SIZE; */ + break; + case PCI_1_MEM3: + sizeReg = PCI_1MEMORY3_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY3_SIZE; */ + break; +#endif /* INCLUDE_PCI_1 */ + default: + return 0x0; + } + /* If the memory window is disabled, retrun size = 0 */ + if (MemoryGetMemWindowStatus (PCI_0_IO_WINDOW << pciWindow) + == MEM_WINDOW_DISABLED) + return 0; + GT_REG_READ (sizeReg, &size); + size = ((size << 16) | 0xffff) + 1; + return size; +} + +/******************************************************************************* +* memoryGetDeviceWidth - Returns the width of a given device. +* DESCRIPTION: +* The MV's device interface supports up to 32 Bit wide devices. A device +* can have a 1, 2, 4 or 8 Bytes data width. This function returns the +* width of a device as defined by the user or the operating system. +* INPUT: +* device - Selects one of the five devices as defined in Memory.h. +* OUTPUT: +* None. +* RETURN: +* Device width in Bytes (1,2,4 or 8), 0 if error had occurred. +*******************************************************************************/ +unsigned int memoryGetDeviceWidth (DEVICE device) +{ + unsigned int width; + unsigned int regValue; + + GT_REG_READ (DEVICE_BANK0PARAMETERS + device * 4, ®Value); + width = (regValue & (BIT20 | BIT21)) >> 20; + return (BIT0 << width); +} + +/******************************************************************************* +* memoryMapBank - Set new base address and size for one of the memory +* banks. +* +* DESCRIPTION: +* The CPU interface address decoding map consists of 21 address windows +* for the different devices (e.g. CS[3:0] ,PCI0 Mem 0/1/2/3...). Each +* window can have a minimum of 1Mbytes of address space, and up to 4Gbyte +* space. Each address window is defined by two registers - base and size. +* The CPU address is compared with the values in the various CPU windows +* until a match is found and the address is than targeted to that window. +* This function sets new base and size for one the memory banks +* (CS0 - CS3). It is the programmer`s responsibility to make sure that +* there are no conflicts with other memory spaces. When two memory spaces +* overlap, the MV’s behavior is not defined .If a bank needs to be closed, +* set the ’bankLength’ parameter size to 0x0. +* +* INPUT: +* bank - One of the memory banks (CS0-CS3) as defined in gtMemory.h. +* bankBase - The memory bank base address. +* bankLength - The memory bank size. This function will decrement the +* 'bankLength' parameter by one and then check if the size is +* valid. A valid size must be programed from LSB to MSB as +* sequence of ‘1’s followed by sequence of ‘0’s. +* To close a memory window simply set the size to 0. +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* OUTPUT: +* None. +* RETURN: +* False for invalid size, true otherwise. +* +* CAUTION: PCI_functions must be implemented later To_do !!!!!!!!!!!!!!!!! +* +*******************************************************************************/ + +bool memoryMapBank (MEMORY_BANK bank, unsigned int bankBase, + unsigned int bankLength) +{ + unsigned int newBase, newSize, baseReg, sizeReg, temp, rShift; + +/* PCI_INTERNAL_BAR pciBAR; */ + + switch (bank) { + case BANK0: + baseReg = SCS_0_LOW_DECODE_ADDRESS; /*CS_0_BASE_ADDR; */ + sizeReg = SCS_0_HIGH_DECODE_ADDRESS; /*CS_0_SIZE; */ +/* pciBAR = PCI_CS0_BAR; */ + break; + case BANK1: + baseReg = SCS_1_LOW_DECODE_ADDRESS; /*CS_1_BASE_ADDR; */ + sizeReg = SCS_1_HIGH_DECODE_ADDRESS; /*CS_1_SIZE; */ + /* pciBAR = SCS_0_HIGH_DECODE_ADDRESS; */ /*PCI_CS1_BAR; */ + break; + case BANK2: + baseReg = SCS_2_LOW_DECODE_ADDRESS; /*CS_2_BASE_ADDR; */ + sizeReg = SCS_2_HIGH_DECODE_ADDRESS; /*CS_2_SIZE; */ +/* pciBAR = PCI_CS2_BAR;*/ + break; + case BANK3: + baseReg = SCS_3_LOW_DECODE_ADDRESS; /*CS_3_BASE_ADDR; */ + sizeReg = SCS_3_HIGH_DECODE_ADDRESS; /*CS_3_SIZE; */ +/* pciBAR = PCI_CS3_BAR; */ + break; + default: + return false; + } + /* If the size is 0, the window will be disabled */ + if (bankLength == 0) { + MemoryDisableWindow (CS_0_WINDOW << bank); + /* Disable the BAR from the PCI slave side */ +/* gtPci0DisableInternalBAR(pciBAR); */ +/* gtPci1DisableInternalBAR(pciBAR); */ + return true; + } + /* The base address must be aligned to the size */ + if ((bankBase % bankLength) != 0) { + return false; + } + if (bankLength >= MINIMUM_MEM_BANK_SIZE) { + newBase = bankBase >> 16; + newSize = bankLength >> 16; + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + temp = newSize - 1; + for (rShift = 0; rShift < 16; rShift++) { + temp = temp >> rShift; + if ((temp & 0x1) == 0) { /* Either we got to the last '1' */ + /* or the size is not valid */ + if (temp > 0x0) + return false; + else + break; + } + } +#ifdef DEBUG + { + unsigned int oldBase, oldSize; + + GT_REG_READ (baseReg, &oldBase); + GT_REG_READ (sizeReg + 8, &oldSize); + + printf ("b%d Base:%x Size:%x -> Base:%x Size:%x\n", + bank, oldBase, oldSize, newBase, newSize); + } +#endif + /* writing the new values */ + GT_REG_WRITE (baseReg, newBase); + GT_REG_WRITE (sizeReg, newSize - 1); + /* Enable back the window */ + MemoryEnableWindow (CS_0_WINDOW << bank); + /* Enable the BAR from the PCI slave side */ +/* gtPci0EnableInternalBAR(pciBAR); */ +/* gtPci1EnableInternalBAR(pciBAR); */ + return true; + } + return false; +} + + +/******************************************************************************* +* memoryMapDeviceSpace - Set new base address and size for one of the device +* windows. +* +* DESCRIPTION: +* The CPU interface address decoding map consists of 21 address windows +* for the different devices (e.g. CS[3:0] ,PCI0 Mem 0/1/2/3...). Each +* window can have a minimum of 1Mbytes of address space, and up to 4Gbyte +* space. Each address window is defined by two registers - base and size. +* The CPU address is compared with the values in the various CPU windows +* until a match is found and the address is than targeted to that window. +* This function sets new base and size for one the device windows +* (DEV_CS0 - DEV_CS3). It is the programmer`s responsibility to make sure +* that there are no conflicts with other memory spaces. When two memory +* spaces overlap, the MV’s behavior is not defined .If a device window +* needs to be closed, set the 'deviceLength' parameter size to 0x0. +* +* INPUT: +* device - One of the device windows (DEV_CS0-DEV_CS3) as +* defined in gtMemory.h. +* deviceBase - The device window base address. +* deviceLength - The device window size. This function will decrement +* the 'deviceLength' parameter by one and then +* check if the size is valid. A valid size must be +* programed from LSB to MSB as sequence of ‘1’s +* followed by sequence of ‘0’s. +* To close a memory window simply set the size to 0. +* +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* +* OUTPUT: +* None. +* +* RETURN: +* False for invalid size, true otherwise. +* +* CAUTION: PCI_functions must be implemented later To_do !!!!!!!!!!!!!!!!! +* +*******************************************************************************/ + +bool memoryMapDeviceSpace (DEVICE device, unsigned int deviceBase, + unsigned int deviceLength) +{ + unsigned int newBase, newSize, baseReg, sizeReg, temp, rShift; + +/* PCI_INTERNAL_BAR pciBAR;*/ + + switch (device) { + case DEVICE0: + baseReg = CS_0_LOW_DECODE_ADDRESS; /*DEV_CS0_BASE_ADDR; */ + sizeReg = CS_0_HIGH_DECODE_ADDRESS; /*DEV_CS0_SIZE; */ +/* pciBAR = PCI_DEV_CS0_BAR; */ + break; + case DEVICE1: + baseReg = CS_1_LOW_DECODE_ADDRESS; /*DEV_CS1_BASE_ADDR; */ + sizeReg = CS_1_HIGH_DECODE_ADDRESS; /*DEV_CS1_SIZE; */ +/* pciBAR = PCI_DEV_CS1_BAR; */ + break; + case DEVICE2: + baseReg = CS_2_LOW_DECODE_ADDRESS; /*DEV_CS2_BASE_ADDR; */ + sizeReg = CS_2_HIGH_DECODE_ADDRESS; /*DEV_CS2_SIZE; */ +/* pciBAR = PCI_DEV_CS2_BAR; */ + break; + case DEVICE3: + baseReg = CS_3_LOW_DECODE_ADDRESS; /*DEV_CS3_BASE_ADDR; */ + sizeReg = CS_3_HIGH_DECODE_ADDRESS; /*DEV_CS3_SIZE; */ +/* pciBAR = PCI_DEV_CS3_BAR; */ + break; + case BOOT_DEVICE: + baseReg = BOOTCS_LOW_DECODE_ADDRESS; /*BOOTCS_BASE_ADDR; */ + sizeReg = BOOTCS_HIGH_DECODE_ADDRESS; /*BOOTCS_SIZE; */ +/* pciBAR = PCI_BOOT_CS_BAR; */ + break; + default: + return false; + } + if (deviceLength == 0) { + MemoryDisableWindow (DEVCS_0_WINDOW << device); + /* Disable the BAR from the PCI slave side */ +/* gtPci0DisableInternalBAR(pciBAR); */ +/* gtPci1DisableInternalBAR(pciBAR); */ + return true; + } + /* The base address must be aligned to the size */ + if ((deviceBase % deviceLength) != 0) { + return false; + } + if (deviceLength >= MINIMUM_DEVICE_WINDOW_SIZE) { + newBase = deviceBase >> 16; + newSize = deviceLength >> 16; + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + temp = newSize - 1; + for (rShift = 0; rShift < 16; rShift++) { + temp = temp >> rShift; + if ((temp & 0x1) == 0) { /* Either we got to the last '1' */ + /* or the size is not valid */ + if (temp > 0x0) + return false; + else + break; + } + } + /* writing the new values */ + GT_REG_WRITE (baseReg, newBase); + GT_REG_WRITE (sizeReg, newSize - 1); + MemoryEnableWindow (DEVCS_0_WINDOW << device); + /* Enable the BAR from the PCI slave side */ +/* gtPci0EnableInternalBAR(pciBAR); */ +/* gtPci1EnableInternalBAR(pciBAR); */ + return true; + } + return false; +} + +/******************************************************************************* +* MemorySetPciWindow - Set new base address and size for one of the PCI +* windows. +* +* DESCRIPTION: +* The CPU interface address decoding map consists of 21 address windows +* for the different devices (e.g. CS[3:0] ,PCI0 Mem 0/1/2/3...). Each +* window can have a minimum of 1Mbytes of address space, and up to 4Gbyte +* space. Each address window is defined by two registers - base and size. +* The CPU address is compared with the values in the various CPU windows +* until a match is found and the address is than targeted to that window. +* This function sets new base and size for one the PCI windows +* (PCI memory0/1/2..). It is the programmer`s responsibility to make sure +* that there are no conflicts with other memory spaces. When two memory +* spaces overlap, the MV’s behavior is not defined .If a PCI window +* needs to be closed, set the 'pciWindowSize' parameter size to 0x0. +* +* INPUT: +* pciWindow - One of the PCI windows as defined in gtMemory.h. +* pciWindowBase - The PCI window base address. +* pciWindowSize - The PCI window size. This function will decrement the +* 'pciWindowSize' parameter by one and then check if the +* size is valid. A valid size must be programed from LSB +* to MSB as sequence of ‘1’s followed by sequence of ‘0’s. +* To close a memory window simply set the size to 0. +* +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* +* OUTPUT: +* None. +* +* RETURN: +* False for invalid size, true otherwise. +* +*******************************************************************************/ +bool memorySetPciWindow (PCI_MEM_WINDOW pciWindow, unsigned int pciWindowBase, + unsigned int pciWindowSize) +{ + unsigned int currentLow, baseAddrReg, sizeReg, temp, rShift; + + switch (pciWindow) { + case PCI_0_IO: + baseAddrReg = PCI_1I_O_LOW_DECODE_ADDRESS; /*PCI_0_IO_BASE_ADDR; */ + sizeReg = PCI_0I_O_HIGH_DECODE_ADDRESS; /*PCI_0_IO_SIZE; */ + break; + case PCI_0_MEM0: + baseAddrReg = PCI_0MEMORY0_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY0_BASE_ADDR; */ + sizeReg = PCI_0MEMORY0_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY0_SIZE; */ + break; + case PCI_0_MEM1: + baseAddrReg = PCI_0MEMORY1_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY1_BASE_ADDR; */ + sizeReg = PCI_0MEMORY1_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY1_SIZE; */ + break; + case PCI_0_MEM2: + baseAddrReg = PCI_0MEMORY2_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY2_BASE_ADDR; */ + sizeReg = PCI_0MEMORY2_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY2_SIZE; */ + break; + case PCI_0_MEM3: + baseAddrReg = PCI_0MEMORY3_LOW_DECODE_ADDRESS; /*PCI_0_MEMORY3_BASE_ADDR; */ + sizeReg = PCI_0MEMORY3_HIGH_DECODE_ADDRESS; /*PCI_0_MEMORY3_SIZE; */ + break; +#ifdef INCLUDE_PCI_1 + case PCI_1_IO: + baseAddrReg = PCI_1I_O_LOW_DECODE_ADDRESS; /*PCI_1_IO_BASE_ADDR; */ + sizeReg = PCI_1I_O_HIGH_DECODE_ADDRESS; /*PCI_1_IO_SIZE; */ + break; + case PCI_1_MEM0: + baseAddrReg = PCI_1MEMORY0_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY0_BASE_ADDR; */ + sizeReg = PCI_1MEMORY0_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY0_SIZE; */ + break; + case PCI_1_MEM1: + baseAddrReg = PCI_1MEMORY1_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY1_BASE_ADDR; */ + sizeReg = PCI_1MEMORY1_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY1_SIZE; */ + break; + case PCI_1_MEM2: + baseAddrReg = PCI_1MEMORY2_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY2_BASE_ADDR; */ + sizeReg = PCI_1MEMORY2_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY2_SIZE; */ + break; + case PCI_1_MEM3: + baseAddrReg = PCI_1MEMORY3_LOW_DECODE_ADDRESS; /*PCI_1_MEMORY3_BASE_ADDR; */ + sizeReg = PCI_1MEMORY3_HIGH_DECODE_ADDRESS; /*PCI_1_MEMORY3_SIZE; */ + break; +#endif /* INCLUDE_PCI_1 */ + default: + return false; + } + if (pciWindowSize == 0) { + MemoryDisableWindow (PCI_0_IO_WINDOW << pciWindow); + return true; + } + /* The base address must be aligned to the size */ + if ((pciWindowBase % pciWindowSize) != 0) { + return false; + } + if (pciWindowSize >= MINIMUM_PCI_WINDOW_SIZE) { + pciWindowBase >>= 16; + pciWindowSize >>= 16; + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + temp = pciWindowSize - 1; + for (rShift = 0; rShift < 16; rShift++) { + temp = temp >> rShift; + if ((temp & 0x1) == 0) { /* Either we got to the last '1' */ + /* or the size is not valid */ + if (temp > 0x0) + return false; + else + break; + } + } + GT_REG_WRITE (sizeReg, pciWindowSize - 1); + GT_REG_READ (baseAddrReg, ¤tLow); + pciWindowBase = + (pciWindowBase & 0xfffff) | (currentLow & 0xfff00000); + GT_REG_WRITE (baseAddrReg, pciWindowBase); + MemoryEnableWindow (PCI_0_IO_WINDOW << pciWindow); + return true; + } + return false; +} + +/******************************************************************************* +* memoryMapInternalRegistersSpace - Sets new base address for the internal +* registers memory space. +* +* DESCRIPTION: +* This function set new base address for the internal register’s memory +* space (the size is fixed and cannot be modified). The function does not +* handle overlapping with other memory spaces, it is the programer's +* responsibility to ensure that overlapping does not occur. +* When two memory spaces overlap, the MV’s behavior is not defined. +* +* INPUT: +* internalRegBase - new base address for the internal register’s memory +* space. +* +* OUTPUT: +* None. +* +* RETURN: +* true on success, false on failure +* +*******************************************************************************/ +/******************************************************************** +* memoryMapInternalRegistersSpace - Sets new base address for the internals +* registers. +* +* INPUTS: unsigned int internalRegBase - The new base address. +* RETURNS: true on success, false on failure +*********************************************************************/ +bool memoryMapInternalRegistersSpace (unsigned int internalRegBase) +{ + unsigned int currentValue; + unsigned int internalValue = internalRegBase; + + internalRegBase = (internalRegBase >> 16); + GT_REG_READ (INTERNAL_SPACE_DECODE, ¤tValue); + internalRegBase = (currentValue & 0xff000000) | internalRegBase; + GT_REG_WRITE (INTERNAL_SPACE_DECODE, internalRegBase); + /* initializing also the global variable 'internalRegBaseAddr' */ +/* gtInternalRegBaseAddr = internalValue; */ + INTERNAL_REG_BASE_ADDR = internalValue; + return true; +} + +/******************************************************************************* +* memoryGetInternalRegistersSpace - Returns the internal registers Base +* address. +* +* DESCRIPTION: +* This function returns the base address of the internal register’s +* memory space . +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32 bit base address of the internal register’s memory space. +* +*******************************************************************************/ +unsigned int memoryGetInternalRegistersSpace (void) +{ + unsigned int currentValue = 0; + + GT_REG_READ (INTERNAL_SPACE_DECODE, ¤tValue); + return ((currentValue & 0x000fffff) << 16); +} + +/******************************************************************************* +* gtMemoryGetInternalSramBaseAddr - Returns the integrated SRAM base address. +* +* DESCRIPTION: +* The Atlantis incorporate integrated 2Mbit SRAM for general use. This +* funcnion return the SRAM's base address. +* INPUT: +* None. +* OUTPUT: +* None. +* RETURN: +* 32 bit SRAM's base address. +* +*******************************************************************************/ +unsigned int memoryGetInternalSramBaseAddr (void) +{ + return ((GTREGREAD (INTEGRATED_SRAM_BASE_ADDR) & 0xfffff) << 16); +} + +/******************************************************************************* +* gtMemorySetInternalSramBaseAddr - Set the integrated SRAM base address. +* +* DESCRIPTION: +* The Atlantis incorporate integrated 2Mbit SRAM for general use. This +* function sets a new base address to the SRAM . +* INPUT: +* sramBaseAddress - The SRAM's base address. +* OUTPUT: +* None. +* RETURN: +* None. +* +*******************************************************************************/ +void gtMemorySetInternalSramBaseAddr (unsigned int sramBaseAddress) +{ + GT_REG_WRITE (INTEGRATED_SRAM_BASE_ADDR, sramBaseAddress >> 16); +} + +/******************************************************************************* +* memorySetProtectRegion - Set protection mode for one of the 8 regions. +* +* DESCRIPTION: +* The CPU interface supports configurable access protection. This includes +* up to eight address ranges defined to a different protection type : +* whether the address range is cacheable or not, whether it is writable or +* not , and whether it is accessible or not. A Low and High registers +* define each window while the minimum address range of each window is +* 1Mbyte. An address driven by the CPU, in addition to the address +* decoding and remapping process, is compared against the eight Access +* Protection Low/High registers , if an address matches one of the windows +* , the MV device checks the transaction type against the protection bits +* defined in CPU Access Protection register, to determine if the access is +* allowed. This function set a protection mode to one of the 8 possible +* regions. +* NOTE: +* The CPU address windows are restricted to a size of 2 power n and the +* start address must be aligned to the window size. For example, if using +* a 16 MB window, the start address bits [23:0] must be 0.The MV's +* internal registers space is not protected, even if the access protection +* windows contain this space. +* +* INPUT: +* region - selects which region to be configured. The values defined in +* gtMemory.h: +* +* - MEM_REGION0 +* - MEM_REGION1 +* - etc. +* +* memAccess - Allows or forbids access (read or write ) to the region. The +* values defined in gtMemory.h: +* +* - MEM_ACCESS_ALLOWED +* - MEM_ACCESS_FORBIDEN +* +* memWrite - CPU write protection to the region. The values defined in +* gtMemory.h: +* +* - MEM_WRITE_ALLOWED +* - MEM_WRITE_FORBIDEN +* +* cacheProtection - Defines whether caching the region is allowed or not. +* The values defined in gtMemory.h: +* +* - MEM_CACHE_ALLOWED +* - MEM_CACHE_FORBIDEN +* +* baseAddress - the region's base Address. +* regionSize - The region's size. This function will decrement the +* 'regionSize' parameter by one and then check if the size +* is valid. A valid size must be programed from LSB to MSB +* as sequence of ‘1’s followed by sequence of ‘0’s. +* To close a memory window simply set the size to 0. +* +* NOTE!!! +* The size must be in 64Kbyte granularity. +* The base address must be aligned to the size. +* +* OUTPUT: +* None. +* +* RETURN: +* False for invalid size, true otherwise. +* +*******************************************************************************/ +bool memorySetProtectRegion (MEMORY_PROTECT_WINDOW window, + MEMORY_ACCESS memAccess, + MEMORY_ACCESS_WRITE memWrite, + MEMORY_CACHE_PROTECT cacheProtection, + unsigned int baseAddress, unsigned int size) +{ + unsigned int dataForReg, temp, rShift; + + if (size == 0) { + GT_REG_WRITE ((CPU_PROTECT_WINDOW_0_SIZE + 0x10 * window), + 0x0); + return true; + } + /* The base address must be aligned to the size. */ + if (baseAddress % size != 0) { + return false; + } + if (size >= MINIMUM_ACCESS_WIN_SIZE) { + baseAddress = ((baseAddress >> 16) & 0xfffff); + dataForReg = baseAddress | ((memAccess << 20) & BIT20) | + ((memWrite << 21) & BIT21) | ((cacheProtection << 22) + & BIT22) | BIT31; + GT_REG_WRITE (CPU_PROTECT_WINDOW_0_BASE_ADDR + 0x10 * window, + dataForReg); + size >>= 16; + /* Checking that the size is a sequence of '1' followed by a + sequence of '0' starting from LSB to MSB. */ + temp = size - 1; + for (rShift = 0; rShift < 16; rShift++) { + temp = temp >> rShift; + if ((temp & 0x1) == 0) { /* Either we got to the last '1' */ + /* or the size is not valid */ + if (temp > 0x0) + return false; + else + break; + } + } + GT_REG_WRITE ((CPU_PROTECT_WINDOW_0_SIZE + 0x10 * window), + size - 1); + return true; + } + return false; +} + +/******************************************************************************* +* gtMemoryDisableProtectRegion - Disable a protected window. +* +* DESCRIPTION: +* This function disable a protected window set by +* 'gtMemorySetProtectRegion' function. +* +* INPUT: +* window - one of the 4 windows ( defined in gtMemory.h ). +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +void memoryDisableProtectRegion (MEMORY_PROTECT_WINDOW window) +{ + RESET_REG_BITS (((CPU_PROTECT_WINDOW_0_BASE_ADDR) + (0x10 * window)), + BIT31); +} + +/******************************************************************************* +* memorySetPciRemapValue - Set a remap value to a PCI memory space target. +* +* DESCRIPTION: +* In addition to the address decoding mechanism, the CPU has an address +* remapping mechanism to be used by every PCI decoding window. Each PCI +* window can be remaped to a desired address target according to the remap +* value within the remap register. The address remapping is useful when a +* CPU address range must be reallocated to a different location on the +* PCI bus. Also, it enables CPU access to a PCI agent located above the +* 4Gbyte space. On system boot, each of the PCI memory spaces is maped to +* a defualt value (see CPU interface section in the MV spec for the +* default values). The remap mechanism does not always produce the desired +* address on the PCI bus because of the remap mechanism way of working +* (to fully understand why, please see the 'Address Remapping' section in +* the MV's spec). Therefor, this function sets a desired remap value to +* one of the PCI memory windows and return the effective address that +* should be used when exiting the PCI memory window. You should ALWAYS use +* the returned value by this function when remapping a PCI window and +* exiting it. If for example the base address of PCI0 memory 0 is +* 0x90000000, the size is 0x03ffffff and the remap value is 0x11000000, +* the function will return the value of 0x91000000 that MUST +* be used to exit this memory window in order to achive the deisred +* remapping. +* +* INPUT: +* memoryWindow - One of the PCI memory windows as defined in Memory.h +* remapValueLow - The low remap value. +* remapValueHigh - The high remap value. +* OUTPUT: +* None. +* +* RETURN: +* The effective base address to exit the PCI, or 0xffffffff if one of the +* parameters is erroneous or the effective base address is higher the top +* decode value. +* +*******************************************************************************/ +unsigned int memorySetPciRemapValue (PCI_MEM_WINDOW memoryWindow, + unsigned int remapValueHigh, + unsigned int remapValueLow) +{ + unsigned int pciMemWindowBaseAddrReg = 0, baseAddrValue = 0; + unsigned int pciMemWindowSizeReg = 0, windowSizeValue = 0; + unsigned int effectiveBaseAddress, remapRegLow, remapRegHigh; + + /* Initializing the base and size variables of the PCI + memory windows */ + switch (memoryWindow) { + case PCI_0_IO: + pciMemWindowBaseAddrReg = PCI_0_IO_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_IO_SIZE; + remapRegLow = PCI_0_IO_ADDR_REMAP; + remapRegHigh = PCI_0_IO_ADDR_REMAP; + break; + case PCI_0_MEM0: + pciMemWindowBaseAddrReg = PCI_0_MEMORY0_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_MEMORY0_SIZE; + remapRegLow = PCI_0_MEMORY0_LOW_ADDR_REMAP; + remapRegHigh = PCI_0_MEMORY0_HIGH_ADDR_REMAP; + break; + case PCI_0_MEM1: + pciMemWindowBaseAddrReg = PCI_0_MEMORY1_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_MEMORY1_SIZE; + remapRegLow = PCI_0_MEMORY1_LOW_ADDR_REMAP; + remapRegHigh = PCI_0_MEMORY1_HIGH_ADDR_REMAP; + break; + case PCI_0_MEM2: + pciMemWindowBaseAddrReg = PCI_0_MEMORY2_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_MEMORY2_SIZE; + remapRegLow = PCI_0_MEMORY2_LOW_ADDR_REMAP; + remapRegHigh = PCI_0_MEMORY2_HIGH_ADDR_REMAP; + break; + case PCI_0_MEM3: + pciMemWindowBaseAddrReg = PCI_0_MEMORY3_BASE_ADDR; + pciMemWindowSizeReg = PCI_0_MEMORY3_SIZE; + remapRegLow = PCI_0_MEMORY3_LOW_ADDR_REMAP; + remapRegHigh = PCI_0_MEMORY3_HIGH_ADDR_REMAP; + break; +#ifdef INCLUDE_PCI_1 + case PCI_1_IO: + pciMemWindowBaseAddrReg = PCI_1_IO_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_IO_SIZE; + remapRegLow = PCI_1_IO_ADDR_REMAP; + remapRegHigh = PCI_1_IO_ADDR_REMAP; + break; + case PCI_1_MEM0: + pciMemWindowBaseAddrReg = PCI_1_MEMORY0_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_MEMORY0_SIZE; + remapRegLow = PCI_1_MEMORY0_LOW_ADDR_REMAP; + remapRegHigh = PCI_1_MEMORY0_HIGH_ADDR_REMAP; + break; + case PCI_1_MEM1: + pciMemWindowBaseAddrReg = PCI_1_MEMORY1_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_MEMORY1_SIZE; + remapRegLow = PCI_1_MEMORY1_LOW_ADDR_REMAP; + remapRegHigh = PCI_1_MEMORY1_HIGH_ADDR_REMAP; + break; + case PCI_1_MEM2: + pciMemWindowBaseAddrReg = PCI_1_MEMORY1_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_MEMORY1_SIZE; + remapRegLow = PCI_1_MEMORY1_LOW_ADDR_REMAP; + remapRegHigh = PCI_1_MEMORY1_HIGH_ADDR_REMAP; + break; + case PCI_1_MEM3: + pciMemWindowBaseAddrReg = PCI_1_MEMORY3_BASE_ADDR; + pciMemWindowSizeReg = PCI_1_MEMORY3_SIZE; + remapRegLow = PCI_1_MEMORY3_LOW_ADDR_REMAP; + remapRegHigh = PCI_1_MEMORY3_HIGH_ADDR_REMAP; + break; +#endif /* INCLUDE_PCI_1 */ + default: + /* Retrun an invalid effective base address */ + return 0xffffffff; + } + /* Writing the remap value to the remap regisers */ + GT_REG_WRITE (remapRegHigh, remapValueHigh); + GT_REG_WRITE (remapRegLow, remapValueLow >> 16); + /* Reading the values from the base address and size registers */ + baseAddrValue = GTREGREAD (pciMemWindowBaseAddrReg) & 0xfffff; + windowSizeValue = GTREGREAD (pciMemWindowSizeReg) & 0xffff; + /* Start calculating the effective Base Address */ + effectiveBaseAddress = baseAddrValue << 16; + /* The effective base address will be combined from the chopped (if any) + remap value (according to the size value and remap mechanism) and the + window's base address */ + effectiveBaseAddress |= + (((windowSizeValue << 16) | 0xffff) & remapValueLow); + /* If the effectiveBaseAddress exceed the window boundaries return an + invalid value. */ + if (effectiveBaseAddress > + ((baseAddrValue << 16) + ((windowSizeValue << 16) | 0xffff))) + return 0xffffffff; + return effectiveBaseAddress; +} + +/******************************************************************** +* memorySetRegionSnoopMode - This function modifys one of the 4 regions which +* supports Cache Coherency. +* +* +* Inputs: SNOOP_REGION region - One of the four regions. +* SNOOP_TYPE snoopType - There is four optional Types: +* 1. No Snoop. +* 2. Snoop to WT region. +* 3. Snoop to WB region. +* 4. Snoop & Invalidate to WB region. +* unsigned int baseAddress - Base Address of this region. +* unsigned int topAddress - Top Address of this region. +* Returns: false if one of the parameters is wrong and true else +*********************************************************************/ +/* evb6260 code */ +#if 0 +bool memorySetRegionSnoopMode(MEMORY_SNOOP_REGION region, + MEMORY_SNOOP_TYPE snoopType, + unsigned int baseAddress, + unsigned int regionLength) +{ + unsigned int snoopXbaseAddress; + unsigned int snoopXtopAddress; + unsigned int data; + unsigned int snoopHigh = baseAddress + regionLength; + + if( (region > MEM_SNOOP_REGION3) || (snoopType > MEM_SNOOP_WB) ) + return false; + snoopXbaseAddress = SNOOP_BASE_ADDRESS_0 + 0x10 * region; + snoopXtopAddress = SNOOP_TOP_ADDRESS_0 + 0x10 * region; + if(regionLength == 0) /* closing the region */ + { + GT_REG_WRITE(snoopXbaseAddress,0x0000ffff); + GT_REG_WRITE(snoopXtopAddress,0); + return true; + } + baseAddress = baseAddress & 0xffff0000; + data = (baseAddress >> 16) | snoopType << 16; + GT_REG_WRITE(snoopXbaseAddress,data); + snoopHigh = (snoopHigh & 0xfff00000) >> 20; + GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1); + return true; +} +#endif + +/******************************************************************** +* memoryRemapAddress - This fubction used for address remapping. +* +* +* Inputs: regOffset: remap register +* remapValue : +* Returns: false if one of the parameters is erroneous,true otherwise. +* +* Not needed function To_do !!!! +*********************************************************************/ +bool memoryRemapAddress (unsigned int remapReg, unsigned int remapValue) +{ + unsigned int valueForReg; + + valueForReg = (remapValue & 0xfff00000) >> 20; + GT_REG_WRITE (remapReg, valueForReg); + return true; +} + +/******************************************************************************* +* memoryGetDeviceParam - Extract the device parameters from the device bank +* parameters register. +* +* DESCRIPTION: +* To allow interfacing with very slow devices and fast synchronous SRAMs, +* each device can be programed to different timing parameters. Each bank +* has its own parameters register. Bank width can be programmed to 8, 16, +* or 32-bits. Bank timing parameters can be programmed to support +* different device types (e.g. Sync Burst SRAM, Flash , ROM, I/O +* Controllers). The MV allows you to set timing parameters and width for +* each device through parameters register . +* This function extracts the parameters described from the Device Bank +* parameters register and fills the given 'deviceParam' (defined in +* gtMemory.h) structure with the read data. +* +* INPUT: +* deviceParam - pointer to a structure DEVICE_PARAM (defined in +* Memory.h).For details about each structure field please +* see the device timing parameter section in the MV +* datasheet. +* deviceNum - Select on of the five device banks (defined in +* Memory.h) : +* +* - DEVICE0 +* - DEVICE1 +* - DEVICE2 +* - etc. +* +* OUTPUT: +* None. +* +* RETURN: +* false if one of the parameters is erroneous,true otherwise. +* +*******************************************************************************/ +/******************************************************************** +* memoryGetDeviceParam - This function used for getting device parameters from +* DEVICE BANK PARAMETERS REGISTER +* +* +* Inputs: - deviceParam: STRUCT with paramiters for DEVICE BANK +* PARAMETERS REGISTER +* - deviceNum : number of device +* Returns: false if one of the parameters is erroneous,true otherwise. +*********************************************************************/ + +bool memoryGetDeviceParam (DEVICE_PARAM * deviceParam, DEVICE deviceNum) +{ + unsigned int valueOfReg; + unsigned int calcData; + + if (deviceNum > 4) + return false; + GT_REG_READ (DEVICE_BANK0PARAMETERS + 4 * deviceNum, &valueOfReg); + calcData = (0x7 & valueOfReg) + ((BIT22 & valueOfReg) >> 19); + deviceParam->turnOff = calcData; /* Turn Off */ + + calcData = ((0x78 & valueOfReg) >> 3) + ((BIT23 & valueOfReg) >> 19); + deviceParam->acc2First = calcData; /* Access To First */ + + calcData = ((0x780 & valueOfReg) >> 7) + ((BIT24 & valueOfReg) >> 20); + deviceParam->acc2Next = calcData; /* Access To Next */ + + calcData = + ((0x3800 & valueOfReg) >> 11) + ((BIT25 & valueOfReg) >> 22); + deviceParam->ale2Wr = calcData; /* Ale To Write */ + + calcData = ((0x1c000 & valueOfReg) >> 14) + + ((BIT26 & valueOfReg) >> 23); + deviceParam->wrLow = calcData; /* Write Active */ + + calcData = ((0xe0000 & valueOfReg) >> 17) + + ((BIT27 & valueOfReg) >> 24); + deviceParam->wrHigh = calcData; /* Write High */ + + calcData = ((0x300000 & valueOfReg) >> 20); + deviceParam->deviceWidth = (BIT0 << calcData); /* In bytes */ + calcData = ((0x30000000 & valueOfReg) >> 28); + deviceParam->badrSkew = calcData; /* Cycles gap between BAdr + toggle to read data sample. */ + calcData = ((0x40000000 & valueOfReg) >> 30); + deviceParam->DPEn = calcData; /* Data Parity enable */ + return true; +} + +/******************************************************************************* +* memorySetDeviceParam - Set new parameters for a device. +* +* +* DESCRIPTION: +* To allow interfacing with very slow devices and fast synchronous SRAMs, +* each device can be programed to different timing parameters. Each bank +* has its own parameters register. Bank width can be programmed to 8, 16, +* or 32-bits. Bank timing parameters can be programmed to support +* different device types (e.g. Sync Burst SRAM, Flash , ROM, I/O +* Controllers). The MV allows you to set timing parameters and width for +* each device through parameters register. This function set new +* parameters to a device Bank from the delivered structure 'deviceParam' +* (defined in gtMemory.h). The structure must be initialized with data +* prior to the use of these function. +* +* INPUT: +* deviceParam - pointer to a structure DEVICE_PARAM (defined in +* Memory.h).For details about each structure field please +* see the device timing parameter section in the MV +* datasheet. +* deviceNum - Select on of the five device banks (defined in +* Memory.h) : +* +* - DEVICE0 +* - DEVICE1 +* - DEVICE2 +* - etc. +* +* OUTPUT: +* None. +* +* RETURN: +* false if one of the parameters is erroneous,true otherwise. +* +*******************************************************************************/ +/******************************************************************** +* memorySetDeviceParam - This function used for setting device parameters to +* DEVICE BANK PARAMETERS REGISTER +* +* +* Inputs: - deviceParam: STRUCT for store paramiters from DEVICE BANK +* PARAMETERS REGISTER +* - deviceNum : number of device +* Returns: false if one of the parameters is erroneous,true otherwise. +*********************************************************************/ +bool memorySetDeviceParam (DEVICE_PARAM * deviceParam, DEVICE deviceNum) +{ + unsigned int valueForReg; + + if ((deviceParam->turnOff > 0x7) || (deviceParam->acc2First > 0xf) || + (deviceParam->acc2Next > 0xf) || (deviceParam->ale2Wr > 0x7) || + (deviceParam->wrLow > 0x7) || (deviceParam->wrHigh > 0x7) || + (deviceParam->badrSkew > 0x2) || (deviceParam->DPEn > 0x1)) { + return false; + } + valueForReg = (((deviceParam->turnOff) & 0x7) | + (((deviceParam->turnOff) & 0x8) << 19) | + (((deviceParam->acc2First) & 0xf) << 3) | + (((deviceParam->acc2First) & 0x10) << 19) | + (((deviceParam->acc2Next) & 0xf) << 7) | + (((deviceParam->acc2Next) & 0x10) << 20) | + (((deviceParam->ale2Wr) & 0x7) << 11) | + (((deviceParam->ale2Wr) & 0xf) << 22) | + (((deviceParam->wrLow) & 0x7) << 14) | + (((deviceParam->wrLow) & 0xf) << 23) | + (((deviceParam->wrHigh) & 0x7) << 17) | + (((deviceParam->wrHigh) & 0xf) << 24) | + (((deviceParam->badrSkew) & 0x3) << 28) | + (((deviceParam->DPEn) & 0x1) << 30)); + + /* insert the device width: */ + switch (deviceParam->deviceWidth) { + case 1: + valueForReg = valueForReg | _8BIT; + break; + case 2: + valueForReg = valueForReg | _16BIT; + break; + case 4: + valueForReg = valueForReg | _32BIT; + break; + default: + valueForReg = valueForReg | _8BIT; + break; + } + GT_REG_WRITE (DEVICE_BANK0PARAMETERS + 4 * deviceNum, valueForReg); + return true; +} + +/******************************************************************************* +* MemoryDisableWindow - Disable a memory space by the disable bit. +* DESCRIPTION: +* This function disables one of the 21 availiable windows dedicated for +* the CPU decoding mechanism. Its possible to combine several windows with +* the OR command. +* INPUT: +* window - One or more of the memory windows (defined in gtMemory.h). +* OUTPUT: +* None. +* RETURN: +* None. +*******************************************************************************/ +void MemoryDisableWindow (MEMORY_WINDOW window) +{ + SET_REG_BITS (BASE_ADDR_ENABLE, window); +} + +/******************************************************************************* +* MemoryEnableWindow - Enable a memory space that was disabled by +* 'MemoryDisableWindow'. +* DESCRIPTION: +* This function enables one of the 21 availiable windows dedicated for the +* CPU decoding mechanism. Its possible to combine several windows with the +* OR command. +* INPUT: +* window - One or more of the memory windows (defined in gtMemory.h). +* OUTPUT: +* None. +* RETURN: +* None. +*******************************************************************************/ +void MemoryEnableWindow (MEMORY_WINDOW window) +{ + RESET_REG_BITS (BASE_ADDR_ENABLE, window); +} + +/******************************************************************************* +* MemoryGetMemWindowStatus - This function check whether the memory window is +* disabled or not. +* DESCRIPTION: +* This function checks if the given memory window is closed . +* INPUT: +* window - One or more of the memory windows (defined in gtMemory.h). +* OUTPUT: +* None. +* RETURN: +* True for a closed window, false otherwise . +*******************************************************************************/ +MEMORY_WINDOW_STATUS MemoryGetMemWindowStatus (MEMORY_WINDOW window) +{ + if (GTREGREAD (BASE_ADDR_ENABLE) & window) + return MEM_WINDOW_DISABLED; + return MEM_WINDOW_ENABLED; +} diff --git a/board/Marvell/common/misc.S b/board/Marvell/common/misc.S new file mode 100644 index 0000000..41c3a95 --- /dev/null +++ b/board/Marvell/common/misc.S @@ -0,0 +1,235 @@ +#include <config.h> +#include <74xx_7xx.h> +#include "version.h" + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +#include "../include/mv_gen_reg.h" + +#ifdef CONFIG_ECC + /* Galileo specific asm code for initializing ECC */ + .globl board_relocate_rom +board_relocate_rom: + mflr r7 + /* update the location of the GT registers */ + lis r11, CFG_GT_REGS@h + /* if we're using ECC, we must use the DMA engine to copy ourselves */ + bl start_idma_transfer_0 + bl wait_for_idma_0 + bl stop_idma_engine_0 + + mtlr r7 + blr + + .globl board_init_ecc +board_init_ecc: + mflr r7 + /* NOTE: r10 still contains the location we've been relocated to + * which happens to be TOP_OF_RAM - CFG_MONITOR_LEN */ + + /* now that we're running from ram, init the rest of main memory + * for ECC use */ + lis r8, CFG_MONITOR_LEN@h + ori r8, r8, CFG_MONITOR_LEN@l + + divw r3, r10, r8 + + /* set up the counter, and init the starting address */ + mtctr r3 + li r12, 0 + + /* bytes per transfer */ + mr r5, r8 +about_to_init_ecc: +1: mr r3, r12 + mr r4, r12 + bl start_idma_transfer_0 + bl wait_for_idma_0 + bl stop_idma_engine_0 + add r12, r12, r8 + bdnz 1b + + mtlr r7 + blr + + /* r3: dest addr + * r4: source addr + * r5: byte count + * r11: gt regbase + * trashes: r6, r5 + */ +start_idma_transfer_0: + /* set the byte count, including the OWN bit */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_BYTE_COUNT + stwbrx r5, 0, (r6) + + /* set the source address */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_SOURCE_ADDRESS + stwbrx r4, 0, (r6) + + /* set the dest address */ + mr r6, r11 + ori r6, r6, CHANNEL0_DMA_DESTINATION_ADDRESS + stwbrx r3, 0, (r6) + + /* set the next record pointer */ + li r5, 0 + mr r6, r11 + ori r6, r6, CHANNEL0NEXT_RECORD_POINTER + stwbrx r5, 0, (r6) + + /* set the low control register */ + /* bit 9 is NON chained mode, bit 31 is new style descriptors. + bit 12 is channel enable */ + ori r5, r5, (1 << 12) | (1 << 12) | (1 << 11) + /* 15 shifted by 16 (oris) == bit 31 */ + oris r5, r5, (1 << 15) + mr r6, r11 + ori r6, r6, CHANNEL0CONTROL + stwbrx r5, 0, (r6) + + blr + + /* this waits for the bytecount to return to zero, indicating + * that the trasfer is complete */ +wait_for_idma_0: + mr r5, r11 + lis r6, 0xff + ori r6, r6, 0xffff + ori r5, r5, CHANNEL0_DMA_BYTE_COUNT +1: lwbrx r4, 0, (r5) + and. r4, r4, r6 + bne 1b + + blr + + /* this turns off channel 0 of the idma engine */ +stop_idma_engine_0: + /* shut off the DMA engine */ + li r5, 0 + mr r6, r11 + ori r6, r6, CHANNEL0CONTROL + stwbrx r5, 0, (r6) + + blr +#endif + +#ifdef CFG_BOARD_ASM_INIT + /* NOTE: trashes r3-r7 */ + .globl board_asm_init +board_asm_init: + /* just move the GT registers to where they belong */ + lis r3, CFG_DFL_GT_REGS@h + ori r3, r3, CFG_DFL_GT_REGS@l + lis r4, CFG_GT_REGS@h + ori r4, r4, CFG_GT_REGS@l + li r5, INTERNAL_SPACE_DECODE + + /* test to see if we've already moved */ + lwbrx r6, r5, r4 + andi. r6, r6, 0xffff + /* check loading of R7 is: 0x0F80 should: 0xf800: DONE */ +/* rlwinm r7, r4, 8, 16, 31 + rlwinm r7, r4, 12, 16, 31 */ /* original */ + rlwinm r7, r4, 16, 16, 31 + /* -----------------------------------------------------*/ + cmp cr0, r7, r6 + beqlr + + /* nope, have to move the registers */ + lwbrx r6, r5, r3 + andis. r6, r6, 0xffff + or r6, r6, r7 + stwbrx r6, r5, r3 + + /* now, poll for the change */ +1: lwbrx r7, r5, r4 + cmp cr0, r7, r6 + bne 1b + + /* done! */ + blr +#endif + +/* For use of the debug LEDs */ + .global led_on0_relocated +led_on0_relocated: + xor r21, r21, r21 + xor r18, r18, r18 + lis r18, 0xFC80 + ori r18, r18, 0x8000 + stw r21, 0x0(r18) +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_off0_relocated +led_off0_relocated: + xor r21, r21, r21 + xor r18, r18, r18 + lis r18, 0xFC81 + ori r18, r18, 0x4000 + stw r21, 0x0(r18) +/* stw r18, 0x0(r18) */ + sync + blr + + .global led_on0 +led_on0: + xor r18, r18, r18 + lis r18, 0x1c80 + ori r18, r18, 0x8000 + stw r18, 0x0(r18) + sync + blr + + .global led_off0 +led_off0: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x4000 + stw r18, 0x0(r18) + sync + blr + + .global led_on1 +led_on1: + xor r18, r18, r18 + lis r18, 0x1c80 + ori r18, r18, 0xc000 + stw r18, 0x0(r18) + sync + blr + + .global led_off1 +led_off1: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x8000 + stw r18, 0x0(r18) + sync + blr + + .global led_on2 +led_on2: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0x0000 + stw r18, 0x0(r18) + sync + blr + + .global led_off2 +led_off2: + xor r18, r18, r18 + lis r18, 0x1c81 + ori r18, r18, 0xc000 + stw r18, 0x0(r18) + sync + blr diff --git a/board/Marvell/common/ns16550.c b/board/Marvell/common/ns16550.c new file mode 100644 index 0000000..475445b --- /dev/null +++ b/board/Marvell/common/ns16550.c @@ -0,0 +1,66 @@ +/* + * COM1 NS16550 support + * originally from linux source (arch/ppc/boot/ns16550.c) + * modified to use CFG_ISA_MEM and new defines + * + * further modified by Josh Huber <huber@mclx.com> to support + * the DUART on the Galileo Eval board. (db64360) + */ + +#include <config.h> +#include "ns16550.h" + +#ifdef ZUMA_NTL +/* no 16550 device */ +#else +const NS16550_t COM_PORTS[] = { (NS16550_t) (CFG_DUART_IO + 0), + (NS16550_t) (CFG_DUART_IO + 0x20) +}; + +volatile struct NS16550 *NS16550_init (int chan, int baud_divisor) +{ + volatile struct NS16550 *com_port; + + com_port = (struct NS16550 *) COM_PORTS[chan]; + com_port->ier = 0x00; + com_port->lcr = LCR_BKSE; /* Access baud rate */ + com_port->dll = baud_divisor & 0xff; /* 9600 baud */ + com_port->dlm = (baud_divisor >> 8) & 0xff; + com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */ + com_port->mcr = MCR_DTR | MCR_RTS; /* RTS/DTR */ + + /* Clear & enable FIFOs */ + com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; + return (com_port); +} + +void NS16550_reinit (volatile struct NS16550 *com_port, int baud_divisor) +{ + com_port->ier = 0x00; + com_port->lcr = LCR_BKSE; /* Access baud rate */ + com_port->dll = baud_divisor & 0xff; /* 9600 baud */ + com_port->dlm = (baud_divisor >> 8) & 0xff; + com_port->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */ + com_port->mcr = MCR_DTR | MCR_RTS; /* RTS/DTR */ + + /* Clear & enable FIFOs */ + com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; +} + +void NS16550_putc (volatile struct NS16550 *com_port, unsigned char c) +{ + while ((com_port->lsr & LSR_THRE) == 0); + com_port->thr = c; +} + +unsigned char NS16550_getc (volatile struct NS16550 *com_port) +{ + while ((com_port->lsr & LSR_DR) == 0); + return (com_port->rbr); +} + +int NS16550_tstc (volatile struct NS16550 *com_port) +{ + return ((com_port->lsr & LSR_DR) != 0); +} +#endif diff --git a/board/Marvell/common/ns16550.h b/board/Marvell/common/ns16550.h new file mode 100644 index 0000000..f2ed2ab --- /dev/null +++ b/board/Marvell/common/ns16550.h @@ -0,0 +1,102 @@ +/* + * NS16550 Serial Port + * originally from linux source (arch/ppc/boot/ns16550.h) + * modified slightly to + * have addresses as offsets from CFG_ISA_BASE + * added a few more definitions + * added prototypes for ns16550.c + * reduced no of com ports to 2 + * modifications (c) Rob Taylor, Flying Pig Systems. 2000. + * + * further modified to support the DUART in the Galileo eval board + * modifications (c) Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + */ + +#ifndef __NS16550_H__ +#define __NS16550_H__ + +/* the padding is necessary because on the galileo board the UART is + wired in with the 3 address lines shifted over by 2 bits */ +struct NS16550 +{ + unsigned char rbr; /* 0 = 0-3*/ + int pad1:24; + + unsigned char ier; /* 1 = 4-7*/ + int pad2:24; + + unsigned char fcr; /* 2 = 8-b*/ + int pad3:24; + + unsigned char lcr; /* 3 = c-f*/ + int pad4:24; + + unsigned char mcr; /* 4 = 10-13*/ + int pad5:24; + + unsigned char lsr; /* 5 = 14-17*/ + int pad6:24; + + unsigned char msr; /* 6 =18-1b*/ + int pad7:24; + + unsigned char scr; /* 7 =1c-1f*/ + int pad8:24; +} __attribute__ ((packed)); + +/* aliases */ +#define thr rbr +#define iir fcr +#define dll rbr +#define dlm ier + +#define FCR_FIFO_EN 0x01 /*fifo enable*/ +#define FCR_RXSR 0x02 /*reciever soft reset*/ +#define FCR_TXSR 0x04 /*transmitter soft reset*/ + + +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_DMA_EN 0x04 +#define MCR_TX_DFR 0x08 + + +#define LCR_WLS_MSK 0x03 /* character length slect mask*/ +#define LCR_WLS_5 0x00 /* 5 bit character length */ +#define LCR_WLS_6 0x01 /* 6 bit character length */ +#define LCR_WLS_7 0x02 /* 7 bit character length */ +#define LCR_WLS_8 0x03 /* 8 bit character length */ +#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */ +#define LCR_PEN 0x08 /* Parity eneble*/ +#define LCR_EPS 0x10 /* Even Parity Select*/ +#define LCR_STKP 0x20 /* Stick Parity*/ +#define LCR_SBRK 0x40 /* Set Break*/ +#define LCR_BKSE 0x80 /* Bank select enable*/ + +#define LSR_DR 0x01 /* Data ready */ +#define LSR_OE 0x02 /* Overrun */ +#define LSR_PE 0x04 /* Parity error */ +#define LSR_FE 0x08 /* Framing error */ +#define LSR_BI 0x10 /* Break */ +#define LSR_THRE 0x20 /* Xmit holding register empty */ +#define LSR_TEMT 0x40 /* Xmitter empty */ +#define LSR_ERR 0x80 /* Error */ + +/* useful defaults for LCR*/ +#define LCR_8N1 0x03 + + +#define COM1 0x03F8 +#define COM2 0x02F8 + +volatile struct NS16550 * NS16550_init(int chan, int baud_divisor); +void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c); +unsigned char NS16550_getc(volatile struct NS16550 *com_port); +int NS16550_tstc(volatile struct NS16550 *com_port); +void NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor); + +typedef struct NS16550 *NS16550_t; + +extern const NS16550_t COM_PORTS[]; + +#endif diff --git a/board/Marvell/common/ppc_error_no.h b/board/Marvell/common/ppc_error_no.h new file mode 100644 index 0000000..53687c8 --- /dev/null +++ b/board/Marvell/common/ppc_error_no.h @@ -0,0 +1,164 @@ +/* + * (C) Copyright 2003 + * Ingo Assmus <ingo.assmus@keymile.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * BK Id: SCCS/s.errno.h 1.9 06/05/01 21:45:21 paulus + */ +#ifndef _MV_PPC_ERRNO_H +#define _MV_PPC_ERRNO_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ +#define EDEADLOCK 58 /* File locking deadlock error */ +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 +#define ERESTARTNOHAND 514 /* restart if no handler.. */ +#define ENOIOCTLCMD 515 /* No ioctl command */ + +#define _LAST_ERRNO 515 + +#endif diff --git a/board/Marvell/common/serial.c b/board/Marvell/common/serial.c new file mode 100644 index 0000000..9d0d213 --- /dev/null +++ b/board/Marvell/common/serial.c @@ -0,0 +1,178 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * modified for marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * serial.c - serial support for the gal ev board + */ + +/* supports both the 16650 duart and the MPSC */ + +#include <common.h> +#include <command.h> +#include "../include/memory.h" +#include "serial.h" + +#ifdef CONFIG_DB64360 +#include "../db64360/mpsc.h" +#endif + +#ifdef CONFIG_DB64460 +#include "../db64460/mpsc.h" +#endif + +#include "ns16550.h" + +#ifdef CONFIG_MPSC + + +int serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + +#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2) + int clock_divisor = 230400 / gd->baudrate; +#endif + + mpsc_init (gd->baudrate); + + /* init the DUART chans so that KGDB in the kernel can use them */ +#ifdef CFG_INIT_CHAN1 + NS16550_reinit (COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + NS16550_reinit (COM_PORTS[1], clock_divisor); +#endif + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + mpsc_putchar ('\r'); + + mpsc_putchar (c); +} + +int serial_getc (void) +{ + return mpsc_getchar (); +} + +int serial_tstc (void) +{ + return mpsc_test_char (); +} + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + galbrg_set_baudrate (CONFIG_MPSC_PORT, gd->baudrate); +} + +#else /* ! CONFIG_MPSC */ + +int serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = 230400 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + (void) NS16550_init (0, clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + (void) NS16550_init (1, clock_divisor); +#endif + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + NS16550_putc (COM_PORTS[CFG_DUART_CHAN], '\r'); + + NS16550_putc (COM_PORTS[CFG_DUART_CHAN], c); +} + +int serial_getc (void) +{ + return NS16550_getc (COM_PORTS[CFG_DUART_CHAN]); +} + +int serial_tstc (void) +{ + return NS16550_tstc (COM_PORTS[CFG_DUART_CHAN]); +} + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = 230400 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + NS16550_reinit (COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + NS16550_reinit (COM_PORTS[1], clock_divisor); +#endif +} + +#endif /* CONFIG_MPSC */ + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +void kgdb_serial_init (void) +{ +} + +void putDebugChar (int c) +{ + serial_putc (c); +} + +void putDebugStr (const char *str) +{ + serial_puts (str); +} + +int getDebugChar (void) +{ + return serial_getc (); +} + +void kgdb_interruptible (int yes) +{ + return; +} +#endif /* CFG_CMD_KGDB */ diff --git a/board/Marvell/common/serial.h b/board/Marvell/common/serial.h new file mode 100644 index 0000000..c7fc8c1 --- /dev/null +++ b/board/Marvell/common/serial.h @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * modified for marvell db64360 eval board by + * Ingo Assmus <ingo.assmus@keymile.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* serial.h - mostly useful for DUART serial_init in serial.c */ + +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + +#if 0 + +#define B230400 1 +#define B115200 2 +#define B57600 4 +#define B38400 82 +#define B19200 163 +#define B9600 24 +#define B4800 651 +#define B2400 1302 +#define B1200 2604 +#define B600 5208 +#define B300 10417 +#define B150 20833 +#define B110 28409 +#define BDEFAULT B115200 + + /* this stuff is important to initialize + the DUART channels */ + +#define Scale 0x01L /* distance between port addresses */ +#define COM1 0x000003f8 /* Keyboard */ +#define COM2 0x000002f8 /* Host */ + + +/* Port Definitions relative to base COM port addresses */ +#define DataIn (0x00*Scale) /* data input port */ +#define DataOut (0x00*Scale) /* data output port */ +#define BaudLsb (0x00*Scale) /* baud rate divisor least significant byte */ +#define BaudMsb (0x01*Scale) /* baud rate divisor most significant byte */ +#define Ier (0x01*Scale) /* interrupt enable register */ +#define Iir (0x02*Scale) /* interrupt identification register */ +#define Lcr (0x03*Scale) /* line control register */ +#define Mcr (0x04*Scale) /* modem control register */ +#define Lsr (0x05*Scale) /* line status register */ +#define Msr (0x06*Scale) /* modem status register */ + +/* Bit Definitions for above ports */ +#define LcrDlab 0x80 /* b7: enable baud rate divisor registers */ +#define LcrDflt 0x03 /* b6-0: no parity, 1 stop, 8 data */ + +#define McrRts 0x02 /* b1: request to send (I am ready to xmit) */ +#define McrDtr 0x01 /* b0: data terminal ready (I am alive ready to rcv) */ +#define McrDflt (McrRts|McrDtr) + +#define LsrTxD 0x6000 /* b5: transmit holding register empty (i.e. xmit OK!)*/ + /* b6: transmitter empty */ +#define LsrRxD 0x0100 /* b0: received data ready (i.e. got a byte!) */ + +#define MsrRi 0x0040 /* b6: ring indicator (other guy is ready to rcv) */ +#define MsrDsr 0x0020 /* b5: data set ready (other guy is alive ready to rcv */ +#define MsrCts 0x0010 /* b4: clear to send (other guy is ready to rcv) */ + +#define IerRda 0xf /* b0: Enable received data available interrupt */ + +#endif + +#endif /* __SERIAL_H__ */ |