diff options
Diffstat (limited to 'u-boot/board/mpl')
36 files changed, 10687 insertions, 0 deletions
diff --git a/u-boot/board/mpl/common/common_util.c b/u-boot/board/mpl/common/common_util.c new file mode 100644 index 0000000..d3300ed --- /dev/null +++ b/u-boot/board/mpl/common/common_util.c @@ -0,0 +1,620 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <command.h> +#include <video_fb.h> +#include "common_util.h" +#include <asm/processor.h> +#include <asm/byteorder.h> +#include <i2c.h> +#include <pci.h> +#include <malloc.h> +#include <bzlib.h> + +#ifdef CONFIG_PIP405 +#include "../pip405/pip405.h" +#include <asm/4xx_pci.h> +#endif +#ifdef CONFIG_MIP405 +#include "../mip405/mip405.h" +#include <asm/4xx_pci.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_PATI) +#define FIRM_START 0xFFF00000 +#endif + +extern int mem_test(ulong start, ulong ramsize, int quiet); + +#define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */ +#define IMAGE_SIZE CONFIG_SYS_MONITOR_LEN /* ugly, but it works for now */ + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +static int +mpl_prg(uchar *src, ulong size) +{ + ulong start; + flash_info_t *info; + int i, rc; +#if defined(CONFIG_PATI) + int start_sect; +#endif +#if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) || defined(CONFIG_PATI) + char *copystr = (char *)src; + ulong *magic = (ulong *)src; +#endif + + info = &flash_info[0]; + +#if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) || defined(CONFIG_PATI) + if (uimage_to_cpu (magic[0]) != IH_MAGIC) { + puts("Bad Magic number\n"); + return -1; + } + /* some more checks before we delete the Flash... */ + /* Checking the ISO_STRING prevents to program a + * wrong Firmware Image into the flash. + */ + i = 4; /* skip Magic number */ + while (1) { + if (strncmp(©str[i], "MEV-", 4) == 0) + break; + if (i++ >= 0x100) { + puts("Firmware Image for unknown Target\n"); + return -1; + } + } + /* we have the ISO STRING, check */ + if (strncmp(©str[i], CONFIG_ISO_STRING, sizeof(CONFIG_ISO_STRING)-1) != 0) { + printf("Wrong Firmware Image: %s\n", ©str[i]); + return -1; + } +#if !defined(CONFIG_PATI) + start = 0 - size; + for (i = info->sector_count-1; i > 0; i--) { + info->protect[i] = 0; /* unprotect this sector */ + if (start >= info->start[i]) + break; + } + /* set-up flash location */ + /* now erase flash */ + printf("Erasing at %lx (sector %d) (start %lx)\n", + start,i,info->start[i]); + if ((rc = flash_erase (info, i, info->sector_count-1)) != 0) { + puts("ERROR "); + flash_perror(rc); + return (1); + } + +#else /* #if !defined(CONFIG_PATI */ + start = FIRM_START; + start_sect = -1; + for (i = 0; i < info->sector_count; i++) { + if (start < info->start[i]) { + start_sect = i - 1; + break; + } + } + + info->protect[i - 1] = 0; /* unprotect this sector */ + for (; i < info->sector_count; i++) { + if ((start + size) < info->start[i]) + break; + info->protect[i] = 0; /* unprotect this sector */ + } + + i--; + /* set-up flash location */ + /* now erase flash */ + printf ("Erasing at %lx to %lx (sector %d to %d) (%lx to %lx)\n", + start, start + size, start_sect, i, + info->start[start_sect], info->start[i]); + if ((rc = flash_erase (info, start_sect, i)) != 0) { + puts ("ERROR "); + flash_perror (rc); + return (1); + } +#endif /* defined(CONFIG_PATI) */ + +#elif defined(CONFIG_VCMA9) + start = 0; + for (i = 0; i <info->sector_count; i++) { + info->protect[i] = 0; /* unprotect this sector */ + if (size < info->start[i]) + break; + } + /* set-up flash location */ + /* now erase flash */ + printf("Erasing at %lx (sector %d) (start %lx)\n", + start,0,info->start[0]); + if ((rc = flash_erase (info, 0, i)) != 0) { + puts("ERROR "); + flash_perror(rc); + return (1); + } + +#endif + printf("flash erased, programming from 0x%lx 0x%lx Bytes\n", + (ulong)src, size); + if ((rc = flash_write ((char *)src, start, size)) != 0) { + puts("ERROR "); + flash_perror(rc); + return (1); + } + puts("OK programming done\n"); + return 0; +} + + +static int +mpl_prg_image(uchar *ld_addr) +{ + unsigned long len; + uchar *data; + image_header_t *hdr = (image_header_t *)ld_addr; + int rc; + +#if defined(CONFIG_FIT) + if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { + puts ("Non legacy image format not supported\n"); + return -1; + } +#endif + + if (!image_check_magic (hdr)) { + puts("Bad Magic Number\n"); + return 1; + } + image_print_contents (hdr); + if (!image_check_os (hdr, IH_OS_U_BOOT)) { + puts("No U-Boot Image\n"); + return 1; + } + if (!image_check_type (hdr, IH_TYPE_FIRMWARE)) { + puts("No Firmware Image\n"); + return 1; + } + if (!image_check_hcrc (hdr)) { + puts("Bad Header Checksum\n"); + return 1; + } + puts("Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + puts("Bad Data CRC\n"); + return 1; + } + puts("OK\n"); + + data = (uchar *)image_get_data (hdr); + len = image_get_data_size (hdr); + + if (image_get_comp (hdr) != IH_COMP_NONE) { + uchar *buf; + /* reserve space for uncompressed image */ + if ((buf = malloc(IMAGE_SIZE)) == NULL) { + puts("Insufficient space for decompression\n"); + return 1; + } + + switch (image_get_comp (hdr)) { + case IH_COMP_GZIP: + puts("Uncompressing (GZIP) ... "); + rc = gunzip ((void *)(buf), IMAGE_SIZE, data, &len); + if (rc != 0) { + puts("GUNZIP ERROR\n"); + free(buf); + return 1; + } + puts("OK\n"); + break; +#ifdef CONFIG_BZIP2 + case IH_COMP_BZIP2: + puts("Uncompressing (BZIP2) ... "); + { + uint retlen = IMAGE_SIZE; + rc = BZ2_bzBuffToBuffDecompress ((char *)(buf), &retlen, + (char *)data, len, 0, 0); + len = retlen; + } + if (rc != BZ_OK) { + printf ("BUNZIP2 ERROR: %d\n", rc); + free(buf); + return 1; + } + puts("OK\n"); + break; +#endif + default: + printf ("Unimplemented compression type %d\n", + image_get_comp (hdr)); + free(buf); + return 1; + } + + rc = mpl_prg(buf, len); + free(buf); + } else { + rc = mpl_prg(data, len); + } + + return(rc); +} + +#if !defined(CONFIG_PATI) +void get_backup_values(backup_t *buf) +{ + i2c_read(CONFIG_SYS_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)buf,sizeof(backup_t)); +} + +void set_backup_values(int overwrite) +{ + backup_t back; + int i; + + get_backup_values(&back); + if(!overwrite) { + if(strncmp(back.signature,"MPL\0",4)==0) { + puts("Not possible to write Backup\n"); + return; + } + } + memcpy(back.signature,"MPL\0",4); + i = getenv_f("serial#",back.serial_name,16); + if(i < 0) { + puts("Not possible to write Backup\n"); + return; + } + back.serial_name[16]=0; + i = getenv_f("ethaddr",back.eth_addr,20); + if(i < 0) { + puts("Not possible to write Backup\n"); + return; + } + back.eth_addr[20]=0; + i2c_write(CONFIG_SYS_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t)); +} + +void clear_env_values(void) +{ + backup_t back; + unsigned char env_crc[4]; + + memset(&back,0xff,sizeof(backup_t)); + memset(env_crc,0x00,4); + i2c_write(CONFIG_SYS_DEF_EEPROM_ADDR,I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t)); + i2c_write(CONFIG_SYS_DEF_EEPROM_ADDR,CONFIG_ENV_OFFSET,2,(void *)env_crc,4); +} + +/* + * check crc of "older" environment + */ +int check_env_old_size(ulong oldsize) +{ + ulong crc, len, new; + unsigned off; + uchar buf[64]; + + /* read old CRC */ + eeprom_read (CONFIG_SYS_DEF_EEPROM_ADDR, + CONFIG_ENV_OFFSET, + (uchar *)&crc, sizeof(ulong)); + + new = 0; + len = oldsize; + off = sizeof(long); + len = oldsize-off; + while (len > 0) { + int n = (len > sizeof(buf)) ? sizeof(buf) : len; + + eeprom_read (CONFIG_SYS_DEF_EEPROM_ADDR, CONFIG_ENV_OFFSET+off, buf, n); + new = crc32 (new, buf, n); + len -= n; + off += n; + } + + return (crc == new); +} + +static ulong oldsizes[] = { + 0x200, + 0x800, + 0 +}; + +void copy_old_env(ulong size) +{ + uchar name_buf[64]; + uchar value_buf[0x800]; + uchar c; + ulong len; + unsigned off; + uchar *name, *value; + + name = &name_buf[0]; + value = &value_buf[0]; + len=size; + off = sizeof(long); + while (len > off) { + eeprom_read (CONFIG_SYS_DEF_EEPROM_ADDR, CONFIG_ENV_OFFSET+off, &c, 1); + if(c != '=') { + *name++=c; + off++; + } + else { + *name++='\0'; + off++; + do { + eeprom_read (CONFIG_SYS_DEF_EEPROM_ADDR, CONFIG_ENV_OFFSET+off, &c, 1); + *value++=c; + off++; + if(c == '\0') + break; + } while(len > off); + name = &name_buf[0]; + value = &value_buf[0]; + if(strncmp((char *)name,"baudrate",8)!=0) { + setenv((char *)name,(char *)value); + } + + } + } +} + + +void check_env(void) +{ + char *s; + int i=0; + char buf[32]; + backup_t back; + + s=getenv("serial#"); + if(!s) { + while(oldsizes[i]) { + if(check_env_old_size(oldsizes[i])) + break; + i++; + } + if(!oldsizes[i]) { + /* no old environment has been found */ + get_backup_values (&back); + if (strncmp (back.signature, "MPL\0", 4) == 0) { + sprintf (buf, "%s", back.serial_name); + setenv ("serial#", buf); + sprintf (buf, "%s", back.eth_addr); + setenv ("ethaddr", buf); + printf ("INFO: serial# and ethaddr recovered, use saveenv\n"); + return; + } + } + else { + copy_old_env(oldsizes[i]); + puts("INFO: old environment ajusted, use saveenv\n"); + } + } + else { + /* check if back up is set */ + get_backup_values(&back); + if(strncmp(back.signature,"MPL\0",4)!=0) { + set_backup_values(0); + } + } +} + +#endif /* #if !defined(CONFIG_PATI) */ + +int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + ulong ld_addr; + int result; +#if !defined(CONFIG_PATI) + ulong size = IMAGE_SIZE; + ulong src = MULTI_PURPOSE_SOCKET_ADDR; + backup_t back; +#endif + + if (strcmp(argv[1], "flash") == 0) + { +#if defined(CONFIG_CMD_FDC) + if (strcmp(argv[2], "floppy") == 0) { + char *local_args[3]; + extern int do_fdcboot (cmd_tbl_t *, int, int, char *[]); + puts("\nupdating bootloader image from floppy\n"); + local_args[0] = argv[0]; + if(argc==4) { + local_args[1] = argv[3]; + local_args[2] = NULL; + ld_addr=simple_strtoul(argv[3], NULL, 16); + result=do_fdcboot(cmdtp, 0, 2, local_args); + } + else { + local_args[1] = NULL; + ld_addr=CONFIG_SYS_LOAD_ADDR; + result=do_fdcboot(cmdtp, 0, 1, local_args); + } + result=mpl_prg_image((uchar *)ld_addr); + return result; + } +#endif + if (strcmp(argv[2], "mem") == 0) { + if(argc==4) { + ld_addr=simple_strtoul(argv[3], NULL, 16); + } + else { + ld_addr=load_addr; + } + printf ("\nupdating bootloader image from memory at %lX\n",ld_addr); + result=mpl_prg_image((uchar *)ld_addr); + return result; + } +#if !defined(CONFIG_PATI) + if (strcmp(argv[2], "mps") == 0) { + puts("\nupdating bootloader image from MPS\n"); + result=mpl_prg((uchar *)src,size); + return result; + } +#endif /* #if !defined(CONFIG_PATI) */ + } +#if !defined(CONFIG_PATI) + if (strcmp(argv[1], "clearenvvalues") == 0) + { + if (strcmp(argv[2], "yes") == 0) + { + clear_env_values(); + return 0; + } + } + if (strcmp(argv[1], "getback") == 0) { + get_backup_values(&back); + back.signature[3]=0; + back.serial_name[16]=0; + back.eth_addr[20]=0; + printf("GetBackUp: signature: %s\n",back.signature); + printf(" serial#: %s\n",back.serial_name); + printf(" ethaddr: %s\n",back.eth_addr); + return 0; + } + if (strcmp(argv[1], "setback") == 0) { + set_backup_values(1); + return 0; + } +#endif + return cmd_usage(cmdtp); +} + + +#if defined(CONFIG_CMD_DOC) +void doc_init (void) +{ + doc_probe(MULTI_PURPOSE_SOCKET_ADDR); +} +#endif + + +#ifdef CONFIG_VIDEO +/****************************************************** + * Routines to display the Board information + * to the screen (since the VGA will be initialized as last, + * we must resend the infos) + */ + +#ifdef CONFIG_CONSOLE_EXTRA_INFO +extern GraphicDevice ctfb; +extern int get_boot_mode(void); + +void video_get_info_str (int line_number, char *info) +{ + /* init video info strings for graphic console */ + PPC4xx_SYS_INFO sys_info; + char rev; + int i,boot; + unsigned long pvr; + char buf[64]; + char buf1[32], buf2[32], buf3[32], buf4[32]; + char cpustr[16]; + char *s, *e, bc; + switch (line_number) + { + case 2: + /* CPU and board infos */ + pvr=get_pvr(); + get_sys_info (&sys_info); + switch (pvr) { + case PVR_405GP_RB: rev='B'; break; + case PVR_405GP_RC: rev='C'; break; + case PVR_405GP_RD: rev='D'; break; + case PVR_405GP_RE: rev='E'; break; + case PVR_405GPR_RB: rev='B'; break; + default: rev='?'; break; + } + if(pvr==PVR_405GPR_RB) + sprintf(cpustr,"PPC405GPr %c",rev); + else + sprintf(cpustr,"PPC405GP %c",rev); + /* Board info */ + i=0; + s=getenv ("serial#"); +#ifdef CONFIG_PIP405 + if (!s || strncmp (s, "PIP405", 6)) { + sprintf(buf,"### No HW ID - assuming PIP405"); + } +#endif +#ifdef CONFIG_MIP405 + if (!s || strncmp (s, "MIP405", 6)) { + sprintf(buf,"### No HW ID - assuming MIP405"); + } +#endif + else { + for (e = s; *e; ++e) { + if (*e == ' ') + break; + } + for (; s < e; ++s) { + if (*s == '_') { + ++s; + break; + } + buf[i++] = *s; + } + sprintf(&buf[i]," SN "); + i+=4; + for (; s < e; ++s) { + buf[i++] = *s; + } + buf[i++]=0; + } + sprintf (info," %s %s %s MHz (%s/%s/%s MHz)", + buf, cpustr, + strmhz (buf1, gd->cpu_clk), + strmhz (buf2, sys_info.freqPLB), + strmhz (buf3, sys_info.freqPLB / sys_info.pllOpbDiv), + strmhz (buf4, sys_info.freqPLB / sys_info.pllExtBusDiv)); + return; + case 3: + /* Memory Info */ + boot = get_boot_mode(); + bc = in8 (CONFIG_PORT_ADDR); + sprintf(info, " %luMB RAM, %luMB Flash Cfg 0x%02X %s %s", + gd->bd->bi_memsize / 0x100000, + gd->bd->bi_flashsize / 0x100000, + bc, + (boot & BOOT_MPS) ? "MPS boot" : "Flash boot", + ctfb.modeIdent); + return; + case 1: + sprintf (buf, "%s",CONFIG_IDENT_STRING); + sprintf (info, " %s", &buf[1]); + return; + } + /* no more info lines */ + *info = 0; + return; +} +#endif /* CONFIG_CONSOLE_EXTRA_INFO */ + +#endif /* CONFIG_VIDEO */ diff --git a/u-boot/board/mpl/common/common_util.h b/u-boot/board/mpl/common/common_util.h new file mode 100644 index 0000000..29cd14f --- /dev/null +++ b/u-boot/board/mpl/common/common_util.h @@ -0,0 +1,45 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +#ifndef _COMMON_UTIL_H_ +#define _COMMON_UTIL_H_ + +typedef struct { + char signature[4]; + char serial_name[17]; /* "MIP405_1000xxxxx" */ + char eth_addr[21]; /* "00:60:C2:0a:00:00" */ +} backup_t; + +void get_backup_values(backup_t *buf); + +#if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) +#define BOOT_MPS 0x01 +#define BOOT_PCI 0x02 +#endif + +void check_env(void); +#if defined(CONFIG_CMD_DOC) +void doc_init (void); +#endif + +#endif /* _COMMON_UTIL_H_ */ diff --git a/u-boot/board/mpl/common/flash.c b/u-boot/board/mpl/common/flash.c new file mode 100644 index 0000000..61f031a --- /dev/null +++ b/u-boot/board/mpl/common/flash.c @@ -0,0 +1,886 @@ +/* + * (C) Copyright 2000, 2001 + * 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 + */ + +/* + * Modified 4/5/2001 + * Wait for completion of each sector erase command issued + * 4/5/2001 + * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com + */ + +/* + * Modified 3/7/2001 + * - adapted for pip405, Denis Peter, MPL AG Switzerland + * TODO: + * clean-up + */ + +#include <common.h> + +#if !defined(CONFIG_PATI) +#include <asm/ppc4xx.h> +#include <asm/processor.h> +#include "common_util.h" +#if defined(CONFIG_MIP405) +#include "../mip405/mip405.h" +#endif +#if defined(CONFIG_PIP405) +#include "../pip405/pip405.h" +#endif +#include <asm/4xx_pci.h> +#else /* defined(CONFIG_PATI) */ +#include <mpc5xx.h> +#endif + +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */ +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); + +void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt); + +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned short + +#define FALSE 0 +#define TRUE 1 + +#if !defined(CONFIG_PATI) + +/*----------------------------------------------------------------------- + * Some CS switching routines: + * + * On PIP/MIP405 we have 3 (4) possible boot mode + * + * - Boot from Flash (Flash CS = CS0, MPS CS = CS1) + * - Boot from MPS (Flash CS = CS1, MPS CS = CS0) + * - Boot from PCI with Flash map (Flash CS = CS0, MPS CS = CS1) + * - Boot from PCI with MPS map (Flash CS = CS1, MPS CS = CS0) + * The flash init is the first board specific routine which is called + * after code relocation (running from SDRAM) + * The first thing we do is to map the Flash CS to the Flash area and + * the MPS CS to the MPS area. Since the flash size is unknown at this + * point, we use the max flash size and the lowest flash address as base. + * + * After flash detection we adjust the size of the CS area accordingly. + * The board_init_r will fill in wrong values in the board init structure, + * but this will be fixed in the misc_init_r routine: + * bd->bi_flashstart=0-flash_info[0].size + * bd->bi_flashsize=flash_info[0].size-CONFIG_SYS_MONITOR_LEN + * bd->bi_flashoffset=0 + * + */ +int get_boot_mode(void) +{ + unsigned long pbcr; + int res = 0; + pbcr = mfdcr (CPC0_PSR); + if ((pbcr & PSR_ROM_WIDTH_MASK) == 0) + /* boot via MPS or MPS mapping */ + res = BOOT_MPS; + if(pbcr & PSR_ROM_LOC) + /* boot via PCI.. */ + res |= BOOT_PCI; + return res; +} + +/* Map the flash high (in boot area) + This code can only be executed from SDRAM (after relocation). +*/ +void setup_cs_reloc(void) +{ + int mode; + /* Since we are relocated, we can set-up the CS finaly + * but first of all, switch off PCI mapping (in case it was a PCI boot) */ + out32r(PMM0MA,0L); + icache_enable (); /* we are relocated */ + /* get boot mode */ + mode=get_boot_mode(); + /* we map the flash high in every case */ + /* first findout on which cs the flash is */ + if(mode & BOOT_MPS) { + /* map flash high on CS1 and MPS on CS0 */ + mtdcr (EBC0_CFGADDR, PB0AP); + mtdcr (EBC0_CFGDATA, MPS_AP); + mtdcr (EBC0_CFGADDR, PB0CR); + mtdcr (EBC0_CFGDATA, MPS_CR); + /* we use the default values (max values) for the flash + * because its real size is not yet known */ + mtdcr (EBC0_CFGADDR, PB1AP); + mtdcr (EBC0_CFGDATA, FLASH_AP); + mtdcr (EBC0_CFGADDR, PB1CR); + mtdcr (EBC0_CFGDATA, FLASH_CR_B); + } + else { + /* map flash high on CS0 and MPS on CS1 */ + mtdcr (EBC0_CFGADDR, PB1AP); + mtdcr (EBC0_CFGDATA, MPS_AP); + mtdcr (EBC0_CFGADDR, PB1CR); + mtdcr (EBC0_CFGDATA, MPS_CR); + /* we use the default values (max values) for the flash + * because its real size is not yet known */ + mtdcr (EBC0_CFGADDR, PB0AP); + mtdcr (EBC0_CFGDATA, FLASH_AP); + mtdcr (EBC0_CFGADDR, PB0CR); + mtdcr (EBC0_CFGDATA, FLASH_CR_B); + } +} + +#endif /* #if !defined(CONFIG_PATI) */ + +unsigned long flash_init (void) +{ + unsigned long size_b0; + int i; + +#if !defined(CONFIG_PATI) + unsigned long size_b1,flashcr,size_reg; + int mode; + extern char version_string; + char *p = &version_string; + + /* Since we are relocated, we can set-up the CS finally */ + setup_cs_reloc(); + /* get and display boot mode */ + mode=get_boot_mode(); + if(mode & BOOT_PCI) + printf("(PCI Boot %s Map) ",(mode & BOOT_MPS) ? + "MPS" : "Flash"); + else + printf("(%s Boot) ",(mode & BOOT_MPS) ? + "MPS" : "Flash"); +#endif /* #if !defined(CONFIG_PATI) */ + /* Init: no FLASHes known */ + for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + size_b0 = flash_get_size((vu_long *)CONFIG_SYS_MONITOR_BASE, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + /* protect the bootloader */ + /* Monitor protection ON by default */ +#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE + flash_protect(FLAG_PROTECT_SET, + CONFIG_SYS_MONITOR_BASE, + CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1, + &flash_info[0]); +#endif +#if !defined(CONFIG_PATI) + /* protect reset vector */ + flash_info[0].protect[flash_info[0].sector_count-1] = 1; + size_b1 = 0 ; + flash_info[0].size = size_b0; + /* set up flash cs according to the size */ + size_reg=(flash_info[0].size >>20); + switch (size_reg) { + case 0: + case 1: i=0; break; /* <= 1MB */ + case 2: i=1; break; /* = 2MB */ + case 4: i=2; break; /* = 4MB */ + case 8: i=3; break; /* = 8MB */ + case 16: i=4; break; /* = 16MB */ + case 32: i=5; break; /* = 32MB */ + case 64: i=6; break; /* = 64MB */ + case 128: i=7; break; /*= 128MB */ + default: + printf("\n #### ERROR, wrong size %ld MByte reset board #####\n",size_reg); + while(1); + } + if(mode & BOOT_MPS) { + /* flash is on CS1 */ + mtdcr(EBC0_CFGADDR, PB1CR); + flashcr = mfdcr (EBC0_CFGDATA); + /* we map the flash high in every case */ + flashcr&=0x0001FFFF; /* mask out address bits */ + flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */ + flashcr|= (i << 17); /* size addr */ + mtdcr(EBC0_CFGADDR, PB1CR); + mtdcr(EBC0_CFGDATA, flashcr); + } + else { + /* flash is on CS0 */ + mtdcr(EBC0_CFGADDR, PB0CR); + flashcr = mfdcr (EBC0_CFGDATA); + /* we map the flash high in every case */ + flashcr&=0x0001FFFF; /* mask out address bits */ + flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */ + flashcr|= (i << 17); /* size addr */ + mtdcr(EBC0_CFGADDR, PB0CR); + mtdcr(EBC0_CFGDATA, flashcr); + } +#if 0 + /* enable this (PIP405/MIP405 only) if you want to test if + the relocation has be done ok. + This will disable both Chipselects */ + mtdcr (EBC0_CFGADDR, PB0CR); + mtdcr (EBC0_CFGDATA, 0L); + mtdcr (EBC0_CFGADDR, PB1CR); + mtdcr (EBC0_CFGDATA, 0L); + printf("CS0 & CS1 switched off for test\n"); +#endif + /* patch version_string */ + for(i=0;i<0x100;i++) { + if(*p=='\n') { + *p=0; + break; + } + p++; + } +#else /* #if !defined(CONFIG_PATI) */ +#ifdef CONFIG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1, + &flash_info[0]); +#endif +#endif /* #if !defined(CONFIG_PATI) */ + return (size_b0); +} + + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *flash; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_SST: printf ("SST "); break; + case FLASH_MAN_INTEL: printf ("Intel "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: printf ("AM29F040 (512 Kbit, uniform sector size)\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_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n"); + break; + case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n"); + break; + case FLASH_INTEL320T: printf ("TE28F320C3 (32 Mbit, top sector size)\n"); + break; + case FLASH_AM640U: printf ("AM29LV640U (64 Mbit, uniform sector size)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + 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) { + /* + * Check if whole sector is erased + */ + if (i != (info->sector_count-1)) + size = info->start[i+1] - info->start[i]; + else + size = info->start[0] + info->size - info->start[i]; + erased = 1; + flash = (volatile unsigned long *)info->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k=0; k<size; k++) { + if (*flash++ != 0xffffffff) { + erased = 0; + break; + } + } + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + info->protect[i] ? "RO " : " "); + } + printf ("\n"); +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + +*/ + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + FLASH_WORD_SIZE value; + ulong base; + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; + + /* Write auto select command: read Manufacturer ID */ + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; + + value = addr2[0]; + /* printf("flash_get_size value: %x\n",value); */ + switch (value) { + case (FLASH_WORD_SIZE)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (FLASH_WORD_SIZE)FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (FLASH_WORD_SIZE)INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + case (FLASH_WORD_SIZE)SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + value = addr2[1]; /* device ID */ + /* printf("Device value %x\n",value); */ + switch (value) { + case (FLASH_WORD_SIZE)AMD_ID_F040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 512 ko */ + break; + case (FLASH_WORD_SIZE)AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + case (FLASH_WORD_SIZE)AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ + case (FLASH_WORD_SIZE)AMD_ID_LV640U: + info->flash_id += FLASH_AM640U; + info->sector_count = 128; + info->size = 0x00800000; + break; /* => 8 MB */ +#if 0 /* enable when device IDs are available */ + + case (FLASH_WORD_SIZE)AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ +#endif + case (FLASH_WORD_SIZE)SST_ID_xF800A: + info->flash_id += FLASH_SST800A; + info->sector_count = 16; + info->size = 0x00100000; + break; /* => 1 MB */ + case (FLASH_WORD_SIZE)INTEL_ID_28F320C3T: + info->flash_id += FLASH_INTEL320T; + info->sector_count = 71; + info->size = 0x00400000; + break; /* => 4 MB */ + + + case (FLASH_WORD_SIZE)SST_ID_xF160A: + info->flash_id += FLASH_SST160A; + info->sector_count = 32; + info->size = 0x00200000; + break; /* => 2 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + /* base address calculation */ + base=0-info->size; + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + (info->flash_id == FLASH_AM040) || + (info->flash_id == FLASH_AM640U)){ + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } + else { + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + if(info->sector_count==71) { + + info->start[i--] = base + info->size - 0x00002000; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000A000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x0000E000; + for (; i >= 0; i--) + info->start[i] = base + i * 0x000010000; + } + else { + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) + info->start[i] = base + i * 0x00010000; + } + } + } + + /* 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 */ + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) + info->protect[i] = 0; + else + info->protect[i] = addr2[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + } + return (info->size); +} + + +int wait_for_DQ7(flash_info_t *info, int sect) +{ + ulong start, now, last; + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); + + start = get_timer (0); + last = start; + while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { + if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return ERR_TIMOUT; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + return ERR_OK; +} + +int intel_wait_for_DQ7(flash_info_t *info, int sect) +{ + ulong start, now, last, status; + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); + + start = get_timer (0); + last = start; + while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { + if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return ERR_TIMOUT; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + status = addr[0] & (FLASH_WORD_SIZE)0x00280028; + /* clear status register */ + addr[0] = (FLASH_WORD_SIZE)0x00500050; + /* check status for block erase fail and VPP low */ + return (status == 0 ? ERR_OK : ERR_NOT_ERASED); +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *addr2; + int flag, prot, sect, l_sect; + int i, rcode = 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_UNKNOWN) { + printf ("Can't erase unknown flash type - aborted\n"); + return 1; + } + + 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(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr2 = (FLASH_WORD_SIZE *)(info->start[sect]); + /* printf("Erasing sector %p\n", addr2); */ /* CLH */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */ + for (i=0; i<50; i++) + udelay(1000); /* wait 1 ms */ + rcode |= wait_for_DQ7(info, sect); + } + else { + if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ + addr2[0] = (FLASH_WORD_SIZE)0x00600060; /* unlock sector */ + addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* sector erase */ + intel_wait_for_DQ7(info, sect); + addr2[0] = (FLASH_WORD_SIZE)0x00200020; /* sector erase */ + addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* sector erase */ + rcode |= intel_wait_for_DQ7(info, sect); + } + else { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */ + rcode |= wait_for_DQ7(info, sect); + } + } + l_sect = sect; + /* + * Wait for each sector to complete, it's more + * reliable. According to AMD Spec, you must + * issue all erase commands within a specified + * timeout. This has been seen to fail, especially + * if printf()s are included (for debug)!! + */ + /* wait_for_DQ7(info, sect); */ + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + +#if 0 + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + wait_for_DQ7(info, l_sect); + +DONE: +#endif + /* reset to read mode */ + addr = (FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + + if (!rcode) + printf (" done\n"); + + return rcode; +} + + +void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt) +{ + int i; + volatile FLASH_WORD_SIZE *addr2; + long c; + c= (long)cnt; + for(i=info->sector_count-1;i>0;i--) + { + if(addr>=info->start[i]) + break; + } + do { + addr2 = (FLASH_WORD_SIZE *)(info->start[i]); + addr2[0] = (FLASH_WORD_SIZE)0x00600060; /* unlock sector setup */ + addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* unlock sector */ + intel_wait_for_DQ7(info, i); + i++; + c-=(info->start[i]-info->start[i-1]); + }while(c>0); +} + + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + + if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ + unlock_intel_sectors(info,addr,cnt); + } + 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; + if((wp % 0x10000)==0) + printf("."); /* show Progress */ + 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); + } + rc=write_word(info, wp, data); + return rc; +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static FLASH_WORD_SIZE *read_val = (FLASH_WORD_SIZE *)0x200000; + +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + volatile FLASH_WORD_SIZE *addr2 = (volatile FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *dest2 = (volatile FLASH_WORD_SIZE *)dest; + volatile FLASH_WORD_SIZE *data2; + ulong start; + ulong *data_p; + int flag; + int i; + + data_p = &data; + data2 = (volatile FLASH_WORD_SIZE *)data_p; + + /* Check if Flash is (sufficiently) erased */ + if ((*((volatile FLASH_WORD_SIZE *)dest) & + (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++) + { + if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ + /* intel style writting */ + dest2[i] = (FLASH_WORD_SIZE)0x00500050; + dest2[i] = (FLASH_WORD_SIZE)0x00400040; + *read_val++ = data2[i]; + dest2[i] = data2[i]; + if (flag) + enable_interrupts(); + /* data polling for D7 */ + start = get_timer (0); + udelay(10); + while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) + { + if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) + return (1); + } + dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */ + udelay(10); + dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */ + if(dest2[i]!=data2[i]) + printf("Error at %p 0x%04X != 0x%04X\n",&dest2[i],dest2[i],data2[i]); + } + else { + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0; + dest2[i] = data2[i]; + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + /* data polling for D7 */ + start = get_timer (0); + while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != + (data2[i] & (FLASH_WORD_SIZE)0x00800080)) { + if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) { + return (1); + } + } + } + } + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/u-boot/board/mpl/common/isa.c b/u-boot/board/mpl/common/isa.c new file mode 100644 index 0000000..5d467b4 --- /dev/null +++ b/u-boot/board/mpl/common/isa.c @@ -0,0 +1,494 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + * + * TODO: clean-up + */ + +#include <common.h> +#include <asm/processor.h> +#include <stdio_dev.h> +#include "isa.h" +#include "piix4_pci.h" +#include "kbd.h" +#include "video.h" + + +#undef ISA_DEBUG + +#ifdef ISA_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#if defined(CONFIG_PIP405) + +extern int drv_isa_kbd_init (void); + +/* fdc (logical device 0) */ +const SIO_LOGDEV_TABLE sio_fdc[] = { + {0x60, 3}, /* set IO to FDPort (3F0) */ + {0x61, 0xF0}, /* set IO to FDPort (3F0) */ + {0x70, 06}, /* set IRQ 6 for FDPort */ + {0x74, 02}, /* set DMA 2 for FDPort */ + {0xF0, 0x05}, /* set to PS2 type */ + {0xF1, 0x00}, /* default value */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; +/* paralell port (logical device 3) */ +const SIO_LOGDEV_TABLE sio_pport[] = { + {0x60, 3}, /* set IO to PPort (378) */ + {0x61, 0x78}, /* set IO to PPort (378) */ + {0x70, 07}, /* set IRQ 7 for PPort */ + {0xF1, 00}, /* set PPort to normal */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; +/* paralell port (logical device 3) Floppy assigned to lpt */ +const SIO_LOGDEV_TABLE sio_pport_fdc[] = { + {0x60, 3}, /* set IO to PPort (378) */ + {0x61, 0x78}, /* set IO to PPort (378) */ + {0x70, 07}, /* set IRQ 7 for PPort */ + {0xF1, 02}, /* set PPort to Floppy */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; +/* uart 1 (logical device 4) */ +const SIO_LOGDEV_TABLE sio_com1[] = { + {0x60, 3}, /* set IO to COM1 (3F8) */ + {0x61, 0xF8}, /* set IO to COM1 (3F8) */ + {0x70, 04}, /* set IRQ 4 for COM1 */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; +/* uart 2 (logical device 5) */ +const SIO_LOGDEV_TABLE sio_com2[] = { + {0x60, 2}, /* set IO to COM2 (2F8) */ + {0x61, 0xF8}, /* set IO to COM2 (2F8) */ + {0x70, 03}, /* set IRQ 3 for COM2 */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; + +/* keyboard controller (logical device 7) */ +const SIO_LOGDEV_TABLE sio_keyboard[] = { + {0x70, 1}, /* set IRQ 1 for keyboard */ + {0x72, 12}, /* set IRQ 12 for mouse */ + {0xF0, 0}, /* disable Port92 (this is a PowerPC!!) */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; + + +/******************************************************************************* +* Config SuperIO FDC37C672 +********************************************************************************/ +unsigned char open_cfg_super_IO(int address) +{ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address,0x55); /* open config */ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address,0x20); /* set address to DEV ID */ + if(in8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address | 0x1)==0x40) /* ok Device ID is correct */ + return TRUE; + else + return FALSE; +} + +void close_cfg_super_IO(int address) +{ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address,0xAA); /* close config */ +} + + +unsigned char read_cfg_super_IO(int address, unsigned char function, unsigned char regaddr) +{ + /* assuming config reg is open */ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address,0x7); /* points to the function reg */ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address | 1,function); /* set the function no */ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address,regaddr); /* sets the address in the function */ + return in8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address | 1); +} + +void write_cfg_super_IO(int address, unsigned char function, unsigned char regaddr, unsigned char data) +{ + /* assuming config reg is open */ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address,0x7); /* points to the function reg */ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address | 1,function); /* set the function no */ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address,regaddr); /* sets the address in the function */ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS | address | 1,data); /* writes the data */ +} + +void isa_write_table(SIO_LOGDEV_TABLE *ldt,unsigned char ldev) +{ + while (ldt->index != 0xFF) { + write_cfg_super_IO(SIO_CFG_PORT, ldev, ldt->index, ldt->val); + ldt++; + } /* endwhile */ +} + +void isa_sio_loadtable(void) +{ + char *s = getenv("floppy"); + /* setup Floppy device 0*/ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_fdc,0); + /* setup parallel port device 3 */ + if(s && !strncmp(s, "lpt", 3)) { + printf("SIO: Floppy assigned to LPT\n"); + /* floppy is assigned to the LPT */ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_pport_fdc,3); + } + else { + /*printf("Floppy assigned to internal port\n");*/ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_pport,3); + } + /* setup Com1 port device 4 */ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_com1,4); + /* setup Com2 port device 5 */ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_com2,5); + /* setup keyboards device 7 */ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_keyboard,7); +} + + +void isa_sio_setup(void) +{ + if(open_cfg_super_IO(SIO_CFG_PORT)==TRUE) + { + isa_sio_loadtable(); + close_cfg_super_IO(0x3F0); + } +} +#endif + +/****************************************************************************** + * IRQ Controller + * we use the Vector mode + */ + +struct isa_irq_action { + interrupt_handler_t *handler; + void *arg; + int count; +}; + +static struct isa_irq_action isa_irqs[16]; + + +/* + * This contains the irq mask for both 8259A irq controllers, + */ +static unsigned int cached_irq_mask = 0xfff9; + +#define cached_imr1 (unsigned char)cached_irq_mask +#define cached_imr2 (unsigned char)(cached_irq_mask>>8) +#define IMR_1 CONFIG_SYS_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_OCW1 +#define IMR_2 CONFIG_SYS_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_OCW1 +#define ICW1_1 CONFIG_SYS_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_ICW1 +#define ICW1_2 CONFIG_SYS_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_ICW1 +#define ICW2_1 CONFIG_SYS_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_ICW2 +#define ICW2_2 CONFIG_SYS_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_ICW2 +#define ICW3_1 ICW2_1 +#define ICW3_2 ICW2_2 +#define ICW4_1 ICW2_1 +#define ICW4_2 ICW2_2 +#define ISR_1 ICW1_1 +#define ISR_2 ICW1_2 + + +void disable_8259A_irq(unsigned int irq) +{ + unsigned int mask = 1 << irq; + + cached_irq_mask |= mask; + if (irq & 8) + out8(IMR_2,cached_imr2); + else + out8(IMR_1,cached_imr1); +} + +void enable_8259A_irq(unsigned int irq) +{ + unsigned int mask = ~(1 << irq); + + cached_irq_mask &= mask; + if (irq & 8) + out8(IMR_2,cached_imr2); + else + out8(IMR_1,cached_imr1); +} +/* +int i8259A_irq_pending(unsigned int irq) +{ + unsigned int mask = 1<<irq; + int ret; + + if (irq < 8) + ret = inb(0x20) & mask; + else + ret = inb(0xA0) & (mask >> 8); + spin_unlock_irqrestore(&i8259A_lock, flags); + + return ret; +} +*/ + +/* + * This function assumes to be called rarely. Switching between + * 8259A registers is slow. + */ +int i8259A_irq_real(unsigned int irq) +{ + int value; + int irqmask = 1<<irq; + + if (irq < 8) { + out8(ISR_1,0x0B); /* ISR register */ + value = in8(ISR_1) & irqmask; + out8(ISR_1,0x0A); /* back to the IRR register */ + return value; + } + out8(ISR_2,0x0B); /* ISR register */ + value = in8(ISR_2) & (irqmask >> 8); + out8(ISR_2,0x0A); /* back to the IRR register */ + return value; +} + +/* + * Careful! The 8259A is a fragile beast, it pretty + * much _has_ to be done exactly like this (mask it + * first, _then_ send the EOI, and the order of EOI + * to the two 8259s is important! + */ +void mask_and_ack_8259A(unsigned int irq) +{ + unsigned int irqmask = 1 << irq; + unsigned int temp_irqmask = cached_irq_mask; + /* + * Lightweight spurious IRQ detection. We do not want + * to overdo spurious IRQ handling - it's usually a sign + * of hardware problems, so we only do the checks we can + * do without slowing down good hardware unnecesserily. + * + * Note that IRQ7 and IRQ15 (the two spurious IRQs + * usually resulting from the 8259A-1|2 PICs) occur + * even if the IRQ is masked in the 8259A. Thus we + * can check spurious 8259A IRQs without doing the + * quite slow i8259A_irq_real() call for every IRQ. + * This does not cover 100% of spurious interrupts, + * but should be enough to warn the user that there + * is something bad going on ... + */ + if (temp_irqmask & irqmask) + goto spurious_8259A_irq; + temp_irqmask |= irqmask; + +handle_real_irq: + if (irq & 8) { + in8(IMR_2); /* DUMMY - (do we need this?) */ + out8(IMR_2,(unsigned char)(temp_irqmask>>8)); + out8(ISR_2,0x60+(irq&7));/* 'Specific EOI' to slave */ + out8(ISR_1,0x62); /* 'Specific EOI' to master-IRQ2 */ + out8(IMR_2,cached_imr2); /* turn it on again */ + } else { + in8(IMR_1); /* DUMMY - (do we need this?) */ + out8(IMR_1,(unsigned char)temp_irqmask); + out8(ISR_1,0x60+irq); /* 'Specific EOI' to master */ + out8(IMR_1,cached_imr1); /* turn it on again */ + } + + return; + +spurious_8259A_irq: + /* + * this is the slow path - should happen rarely. + */ + if (i8259A_irq_real(irq)) + /* + * oops, the IRQ _is_ in service according to the + * 8259A - not spurious, go handle it. + */ + goto handle_real_irq; + + { + static int spurious_irq_mask; + /* + * At this point we can be sure the IRQ is spurious, + * lets ACK and report it. [once per IRQ] + */ + if (!(spurious_irq_mask & irqmask)) { + PRINTF("spurious 8259A interrupt: IRQ%d.\n", irq); + spurious_irq_mask |= irqmask; + } + /* irq_err_count++; */ + /* + * Theoretically we do not have to handle this IRQ, + * but in Linux this does not cause problems and is + * simpler for us. + */ + goto handle_real_irq; + } +} + +void init_8259A(void) +{ + out8(IMR_1,0xff); /* mask all of 8259A-1 */ + out8(IMR_2,0xff); /* mask all of 8259A-2 */ + + out8(ICW1_1,0x11); /* ICW1: select 8259A-1 init */ + out8(ICW2_1,0x20 + 0); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ + out8(ICW3_1,0x04); /* 8259A-1 (the master) has a slave on IR2 */ + out8(ICW4_1,0x01); /* master expects normal EOI */ + out8(ICW1_2,0x11); /* ICW2: select 8259A-2 init */ + out8(ICW2_2,0x20 + 8); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ + out8(ICW3_2,0x02); /* 8259A-2 is a slave on master's IR2 */ + out8(ICW4_2,0x01); /* (slave's support for AEOI in flat mode + is to be investigated) */ + udelay(10000); /* wait for 8259A to initialize */ + out8(IMR_1,cached_imr1); /* restore master IRQ mask */ + udelay(10000); /* wait for 8259A to initialize */ + out8(IMR_2,cached_imr2); /* restore slave IRQ mask */ +} + + +#define PCI_INT_ACK_ADDR 0xEED00000 + +int handle_isa_int(void) +{ + unsigned long irqack; + unsigned char isr1,isr2,irq; + /* first we acknokledge the int via the PCI bus */ + irqack=in32(PCI_INT_ACK_ADDR); + /* now we get the ISRs */ + isr2=in8(ISR_2); + isr1=in8(ISR_1); + irq=(unsigned char)irqack; + irq-=32; +/* if((irq==7)&&((isr1&0x80)==0)) { + PRINTF("IRQ7 detected but not in ISR\n"); + } + else { +*/ /* we should handle cascaded interrupts here also */ + { +/* printf("ISA Irq %d\n",irq); */ + isa_irqs[irq].count++; + if(irq!=2) { /* just swallow the cascade irq 2 */ + if (isa_irqs[irq].handler != NULL) + (*isa_irqs[irq].handler)(isa_irqs[irq].arg); /* call isr */ + else { + PRINTF ("bogus interrupt vector 0x%x\n", irq); + } + } + } + /* issue EOI instruction to clear the IRQ */ + mask_and_ack_8259A(irq); + return 0; +} + + +/****************************************************************** + * Install and free an ISA interrupt handler. + */ + +void isa_irq_install_handler(int vec, interrupt_handler_t *handler, void *arg) +{ + if (isa_irqs[vec].handler != NULL) { + printf ("ISA Interrupt vector %d: handler 0x%x replacing 0x%x\n", + vec, (uint)handler, (uint)isa_irqs[vec].handler); + } + isa_irqs[vec].handler = handler; + isa_irqs[vec].arg = arg; + enable_8259A_irq(vec); + PRINTF ("Install ISA IRQ %d ==> %p, @ %p mask=%04x\n", vec, handler, &isa_irqs[vec].handler,cached_irq_mask); + +} + +void isa_irq_free_handler(int vec) +{ + disable_8259A_irq(vec); + isa_irqs[vec].handler = NULL; + isa_irqs[vec].arg = NULL; + PRINTF ("Free ISA IRQ %d mask=%04x\n", vec, cached_irq_mask); + +} + +/****************************************************************************/ +void isa_init_irq_contr(void) +{ + int i; + /* disable all Interrupts */ + /* first write icws controller 1 */ + for(i=0;i<16;i++) + { + isa_irqs[i].handler=NULL; + isa_irqs[i].arg=NULL; + isa_irqs[i].count=0; + } + init_8259A(); + out8(IMR_2,0xFF); +} +/*************************************************************************/ + +void isa_show_irq(void) +{ + int vec; + + printf ("\nISA Interrupt-Information:\n"); + printf ("Nr Routine Arg Count\n"); + + for (vec=0; vec<16; vec++) { + if (isa_irqs[vec].handler != NULL) { + printf ("%02d %08lx %08lx %d\n", + vec, + (ulong)isa_irqs[vec].handler, + (ulong)isa_irqs[vec].arg, + isa_irqs[vec].count); + } + } +} + +int isa_irq_get_count(int vec) +{ + return(isa_irqs[vec].count); +} + +/****************************************************************** + * Init the ISA bus and devices. + */ + +#if defined(CONFIG_PIP405) + +int isa_init(void) +{ + isa_sio_setup(); + isa_init_irq_contr(); + drv_isa_kbd_init(); + return 0; +} +#endif diff --git a/u-boot/board/mpl/common/isa.h b/u-boot/board/mpl/common/isa.h new file mode 100644 index 0000000..28ed219 --- /dev/null +++ b/u-boot/board/mpl/common/isa.h @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ISA_H_ +#define _ISA_H_ +/* Super IO */ +#define SIO_CFG_PORT 0x3F0 /* Config Port Address */ + +#if defined(CONFIG_PIP405) +/* table fore SIO initialization */ +typedef struct { + const uchar index; + const uchar val; +} SIO_LOGDEV_TABLE; + +typedef struct { + const uchar ldev; + const SIO_LOGDEV_TABLE *ldev_table; +} SIO_TABLE; + + +unsigned char open_cfg_super_IO(int address); +unsigned char read_cfg_super_IO(int address, unsigned char function, unsigned char regaddr); +void write_cfg_super_IO(int address, unsigned char function, unsigned char regaddr, unsigned char data); +void close_cfg_super_IO(int address); +void isa_sio_setup(void); +#endif + +void isa_irq_install_handler(int vec, interrupt_handler_t *handler, void *arg); +void isa_irq_free_handler(int vec); +int handle_isa_int(void); +void isa_init_irq_contr(void); +void isa_show_irq(void); +int isa_irq_get_count(int vec); + + +#endif diff --git a/u-boot/board/mpl/common/kbd.c b/u-boot/board/mpl/common/kbd.c new file mode 100644 index 0000000..b0a9620 --- /dev/null +++ b/u-boot/board/mpl/common/kbd.c @@ -0,0 +1,645 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * + * Source partly derived from: + * linux/drivers/char/pc_keyb.c + * + * + */ +#include <common.h> +#include <asm/processor.h> +#include <stdio_dev.h> +#include "isa.h" +#include "kbd.h" + + +unsigned char kbd_read_status(void); +unsigned char kbd_read_input(void); +void kbd_send_data(unsigned char data); +void disable_8259A_irq(unsigned int irq); +void enable_8259A_irq(unsigned int irq); + +/* used only by send_data - set by keyboard_interrupt */ + + +#undef KBG_DEBUG + +#ifdef KBG_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +#define KBD_STAT_KOBF 0x01 +#define KBD_STAT_IBF 0x02 +#define KBD_STAT_SYS 0x04 +#define KBD_STAT_CD 0x08 +#define KBD_STAT_LOCK 0x10 +#define KBD_STAT_MOBF 0x20 +#define KBD_STAT_TI_OUT 0x40 +#define KBD_STAT_PARERR 0x80 + +#define KBD_INIT_TIMEOUT 1000 /* Timeout in ms for initializing the keyboard */ +#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ +#define KBD_TIMEOUT 2000 /* Timeout in ms for keyboard command acknowledge */ +/* + * Keyboard Controller Commands + */ + +#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ +#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ +#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ +#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ +#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ +#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ +#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ +#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ +#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ +#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ +#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if + initiated by the auxiliary device */ +#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ + +/* + * Keyboard Commands + */ + +#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ +#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ +#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ +#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */ +#define KBD_CMD_RESET 0xFF /* Reset */ + +/* + * Keyboard Replies + */ + +#define KBD_REPLY_POR 0xAA /* Power on reset */ +#define KBD_REPLY_ACK 0xFA /* Command ACK */ +#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ + +/* + * Status Register Bits + */ + +#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ +#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ +#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ +#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ +#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ +#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ +#define KBD_STAT_PERR 0x80 /* Parity error */ + +#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF) + +/* + * Controller Mode Register Bits + */ + +#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ +#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ +#define KBD_MODE_SYS 0x04 /* The system flag (?) */ +#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ +#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ +#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ +#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ +#define KBD_MODE_RFU 0x80 + + +#define KDB_DATA_PORT 0x60 +#define KDB_COMMAND_PORT 0x64 + +#define LED_SCR 0x01 /* scroll lock led */ +#define LED_CAP 0x04 /* caps lock led */ +#define LED_NUM 0x02 /* num lock led */ + +#define KBD_BUFFER_LEN 0x20 /* size of the keyboardbuffer */ + + +static volatile char kbd_buffer[KBD_BUFFER_LEN]; +static volatile int in_pointer = 0; +static volatile int out_pointer = 0; + + +static unsigned char num_lock = 0; +static unsigned char caps_lock = 0; +static unsigned char scroll_lock = 0; +static unsigned char shift = 0; +static unsigned char ctrl = 0; +static unsigned char alt = 0; +static unsigned char e0 = 0; +static unsigned char leds = 0; + +#define DEVNAME "kbd" + +/* Simple translation table for the keys */ + +static unsigned char kbd_plain_xlate[] = { + 0xff,0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t', /* 0x00 - 0x0f */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',0xff, 'a', 's', /* 0x10 - 0x1f */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',0xff,'\\', 'z', 'x', 'c', 'v', /* 0x20 - 0x2f */ + 'b', 'n', 'm', ',', '.', '/',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */ + 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */ + '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */ + '\r',0xff,0xff + }; + +static unsigned char kbd_shift_xlate[] = { + 0xff,0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t', /* 0x00 - 0x0f */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',0xff, 'A', 'S', /* 0x10 - 0x1f */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',0xff, '|', 'Z', 'X', 'C', 'V', /* 0x20 - 0x2f */ + 'B', 'N', 'M', '<', '>', '?',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */ + 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */ + '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */ + '\r',0xff,0xff + }; + +static unsigned char kbd_ctrl_xlate[] = { + 0xff,0x1b, '1',0x00, '3', '4', '5',0x1E, '7', '8', '9', '0',0x1F, '=','\b','\t', /* 0x00 - 0x0f */ + 0x11,0x17,0x05,0x12,0x14,0x18,0x15,0x09,0x0f,0x10,0x1b,0x1d,'\n',0xff,0x01,0x13, /* 0x10 - 0x1f */ + 0x04,0x06,0x08,0x09,0x0a,0x0b,0x0c, ';','\'', '~',0x00,0x1c,0x1a,0x18,0x03,0x16, /* 0x20 - 0x2f */ + 0x02,0x0e,0x0d, '<', '>', '?',0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */ + 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */ + '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */ + '\r',0xff,0xff + }; + +/****************************************************************** + * Init + ******************************************************************/ +int isa_kbd_init(void) +{ + char* result; + result=kbd_initialize(); + if(result==NULL) { + PRINTF("AT Keyboard initialized\n"); + irq_install_handler(25, (interrupt_handler_t *)handle_isa_int, NULL); + isa_irq_install_handler(KBD_INTERRUPT, (interrupt_handler_t *)kbd_interrupt, NULL); + return (1); + } else { + printf("%s\n",result); + return (-1); + } +} + +#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE +extern int overwrite_console (void); +#else +int overwrite_console (void) +{ + return (0); +} +#endif + +int drv_isa_kbd_init (void) +{ + int error; + struct stdio_dev kbddev ; + char *stdinname = getenv ("stdin"); + + if(isa_kbd_init()==-1) + return -1; + memset (&kbddev, 0, sizeof(kbddev)); + strcpy(kbddev.name, DEVNAME); + kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + kbddev.putc = NULL ; + kbddev.puts = NULL ; + kbddev.getc = kbd_getc ; + kbddev.tstc = kbd_testc ; + + error = stdio_register (&kbddev); + if(error==0) { + /* check if this is the standard input device */ + if(strcmp(stdinname,DEVNAME)==0) { + /* reassign the console */ + if(overwrite_console()) { + return 1; + } + error=console_assign(stdin,DEVNAME); + if(error==0) + return 1; + else + return error; + } + return 1; + } + return error; +} + +/****************************************************************** + * Queue handling + ******************************************************************/ +/* puts character in the queue and sets up the in and out pointer */ +void kbd_put_queue(char data) +{ + if((in_pointer+1)==KBD_BUFFER_LEN) { + if(out_pointer==0) { + return; /* buffer full */ + } else{ + in_pointer=0; + } + } else { + if((in_pointer+1)==out_pointer) + return; /* buffer full */ + in_pointer++; + } + kbd_buffer[in_pointer]=data; + return; +} + +/* test if a character is in the queue */ +int kbd_testc(void) +{ + if(in_pointer==out_pointer) + return(0); /* no data */ + else + return(1); +} +/* gets the character from the queue */ +int kbd_getc(void) +{ + char c; + while(in_pointer==out_pointer); + if((out_pointer+1)==KBD_BUFFER_LEN) + out_pointer=0; + else + out_pointer++; + c=kbd_buffer[out_pointer]; + return (int)c; + +} + + +/* set LEDs */ + +void kbd_set_leds(void) +{ + if(caps_lock==0) + leds&=~LED_CAP; /* switch caps_lock off */ + else + leds|=LED_CAP; /* switch on LED */ + if(num_lock==0) + leds&=~LED_NUM; /* switch LED off */ + else + leds|=LED_NUM; /* switch on LED */ + if(scroll_lock==0) + leds&=~LED_SCR; /* switch LED off */ + else + leds|=LED_SCR; /* switch on LED */ + kbd_send_data(KBD_CMD_SET_LEDS); + kbd_send_data(leds); +} + + +void handle_keyboard_event (unsigned char scancode) +{ + unsigned char keycode; + + /* Convert scancode to keycode */ + PRINTF ("scancode %x\n", scancode); + if (scancode == 0xe0) { + e0 = 1; /* special charakters */ + return; + } + if (e0 == 1) { + e0 = 0; /* delete flag */ + if (!(((scancode & 0x7F) == 0x38) || /* the right ctrl key */ + ((scancode & 0x7F) == 0x1D) || /* the right alt key */ + ((scancode & 0x7F) == 0x35) || /* the right '/' key */ + ((scancode & 0x7F) == 0x1C))) + /* the right enter key */ + /* we swallow unknown e0 codes */ + return; + } + /* special cntrl keys */ + switch (scancode) { + case 0x2A: + case 0x36: /* shift pressed */ + shift = 1; + return; /* do nothing else */ + case 0xAA: + case 0xB6: /* shift released */ + shift = 0; + return; /* do nothing else */ + case 0x38: /* alt pressed */ + alt = 1; + return; /* do nothing else */ + case 0xB8: /* alt released */ + alt = 0; + return; /* do nothing else */ + case 0x1d: /* ctrl pressed */ + ctrl = 1; + return; /* do nothing else */ + case 0x9d: /* ctrl released */ + ctrl = 0; + return; /* do nothing else */ + case 0x46: /* scrollock pressed */ + scroll_lock = ~scroll_lock; + kbd_set_leds (); + return; /* do nothing else */ + case 0x3A: /* capslock pressed */ + caps_lock = ~caps_lock; + kbd_set_leds (); + return; + case 0x45: /* numlock pressed */ + num_lock = ~num_lock; + kbd_set_leds (); + return; + case 0xC6: /* scroll lock released */ + case 0xC5: /* num lock released */ + case 0xBA: /* caps lock released */ + return; /* just swallow */ + } + if ((scancode & 0x80) == 0x80) /* key released */ + return; + /* now, decide which table we need */ + if (scancode > (sizeof (kbd_plain_xlate) / sizeof (kbd_plain_xlate[0]))) { /* scancode not in list */ + PRINTF ("unkown scancode %X\n", scancode); + return; /* swallow it */ + } + /* setup plain code first */ + keycode = kbd_plain_xlate[scancode]; + if (caps_lock == 1) { /* caps_lock is pressed, overwrite plain code */ + if (scancode > (sizeof (kbd_shift_xlate) / sizeof (kbd_shift_xlate[0]))) { /* scancode not in list */ + PRINTF ("unkown caps-locked scancode %X\n", scancode); + return; /* swallow it */ + } + keycode = kbd_shift_xlate[scancode]; + if (keycode < 'A') { /* we only want the alphas capital */ + keycode = kbd_plain_xlate[scancode]; + } + } + if (shift == 1) { /* shift overwrites caps_lock */ + if (scancode > (sizeof (kbd_shift_xlate) / sizeof (kbd_shift_xlate[0]))) { /* scancode not in list */ + PRINTF ("unkown shifted scancode %X\n", scancode); + return; /* swallow it */ + } + keycode = kbd_shift_xlate[scancode]; + } + if (ctrl == 1) { /* ctrl overwrites caps_lock and shift */ + if (scancode > (sizeof (kbd_ctrl_xlate) / sizeof (kbd_ctrl_xlate[0]))) { /* scancode not in list */ + PRINTF ("unkown ctrl scancode %X\n", scancode); + return; /* swallow it */ + } + keycode = kbd_ctrl_xlate[scancode]; + } + /* check if valid keycode */ + if (keycode == 0xff) { + PRINTF ("unkown scancode %X\n", scancode); + return; /* swallow unknown codes */ + } + + kbd_put_queue (keycode); + PRINTF ("%x\n", keycode); +} + +/* + * This reads the keyboard status port, and does the + * appropriate action. + * + */ +unsigned char handle_kbd_event(void) +{ + unsigned char status = kbd_read_status(); + unsigned int work = 10000; + + while ((--work > 0) && (status & KBD_STAT_OBF)) { + unsigned char scancode; + + scancode = kbd_read_input(); + + /* Error bytes must be ignored to make the + Synaptics touchpads compaq use work */ + /* Ignore error bytes */ + if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR))) + { + if (status & KBD_STAT_MOUSE_OBF) + ; /* not supported: handle_mouse_event(scancode); */ + else + handle_keyboard_event(scancode); + } + status = kbd_read_status(); + } + if (!work) + PRINTF("pc_keyb: controller jammed (0x%02X).\n", status); + return status; +} + + +/****************************************************************************** + * Lowlevel Part of keyboard section + */ +unsigned char kbd_read_status(void) +{ + return(in8(CONFIG_SYS_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT)); +} + +unsigned char kbd_read_input(void) +{ + return(in8(CONFIG_SYS_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT)); +} + +void kbd_write_command(unsigned char cmd) +{ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT,cmd); +} + +void kbd_write_output(unsigned char data) +{ + out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT, data); +} + +int kbd_read_data(void) +{ + int val; + unsigned char status; + + val = -1; + status = kbd_read_status(); + if (status & KBD_STAT_OBF) { + val = kbd_read_input(); + if (status & (KBD_STAT_GTO | KBD_STAT_PERR)) + val = -2; + } + return val; +} + +int kbd_wait_for_input(void) +{ + unsigned long timeout; + int val; + + timeout = KBD_TIMEOUT; + val=kbd_read_data(); + while(val < 0) + { + if(timeout--==0) + return -1; + udelay(1000); + val=kbd_read_data(); + } + return val; +} + + +int kb_wait(void) +{ + unsigned long timeout = KBC_TIMEOUT * 10; + + do { + unsigned char status = handle_kbd_event(); + if (!(status & KBD_STAT_IBF)) + return 0; /* ok */ + udelay(1000); + timeout--; + } while (timeout); + return 1; +} + +void kbd_write_command_w(int data) +{ + if(kb_wait()) + PRINTF("timeout in kbd_write_command_w\n"); + kbd_write_command(data); +} + +void kbd_write_output_w(int data) +{ + if(kb_wait()) + PRINTF("timeout in kbd_write_output_w\n"); + kbd_write_output(data); +} + +void kbd_send_data(unsigned char data) +{ + unsigned char status; + disable_8259A_irq(1); /* disable interrupt */ + kbd_write_output_w(data); + status = kbd_wait_for_input(); + if (status == KBD_REPLY_ACK) + enable_8259A_irq(1); /* enable interrupt */ +} + + +char * kbd_initialize(void) +{ + int status; + + in_pointer = 0; /* delete in Buffer */ + out_pointer = 0; + /* + * Test the keyboard interface. + * This seems to be the only way to get it going. + * If the test is successful a x55 is placed in the input buffer. + */ + kbd_write_command_w(KBD_CCMD_SELF_TEST); + if (kbd_wait_for_input() != 0x55) + return "Kbd: failed self test"; + /* + * Perform a keyboard interface test. This causes the controller + * to test the keyboard clock and data lines. The results of the + * test are placed in the input buffer. + */ + kbd_write_command_w(KBD_CCMD_KBD_TEST); + if (kbd_wait_for_input() != 0x00) + return "Kbd: interface failed self test"; + /* + * Enable the keyboard by allowing the keyboard clock to run. + */ + kbd_write_command_w(KBD_CCMD_KBD_ENABLE); + status = kbd_wait_for_input(); + /* + * Reset keyboard. If the read times out + * then the assumption is that no keyboard is + * plugged into the machine. + * This defaults the keyboard to scan-code set 2. + * + * Set up to try again if the keyboard asks for RESEND. + */ + do { + kbd_write_output_w(KBD_CMD_RESET); + status = kbd_wait_for_input(); + if (status == KBD_REPLY_ACK) + break; + if (status != KBD_REPLY_RESEND) { + PRINTF("status: %X\n",status); + return "Kbd: reset failed, no ACK"; + } + } while (1); + if (kbd_wait_for_input() != KBD_REPLY_POR) + return "Kbd: reset failed, no POR"; + + /* + * Set keyboard controller mode. During this, the keyboard should be + * in the disabled state. + * + * Set up to try again if the keyboard asks for RESEND. + */ + do { + kbd_write_output_w(KBD_CMD_DISABLE); + status = kbd_wait_for_input(); + if (status == KBD_REPLY_ACK) + break; + if (status != KBD_REPLY_RESEND) + return "Kbd: disable keyboard: no ACK"; + } while (1); + + kbd_write_command_w(KBD_CCMD_WRITE_MODE); + kbd_write_output_w(KBD_MODE_KBD_INT + | KBD_MODE_SYS + | KBD_MODE_DISABLE_MOUSE + | KBD_MODE_KCC); + + /* AMCC powerpc portables need this to use scan-code set 1 -- Cort */ + kbd_write_command_w(KBD_CCMD_READ_MODE); + if (!(kbd_wait_for_input() & KBD_MODE_KCC)) { + /* + * If the controller does not support conversion, + * Set the keyboard to scan-code set 1. + */ + kbd_write_output_w(0xF0); + kbd_wait_for_input(); + kbd_write_output_w(0x01); + kbd_wait_for_input(); + } + kbd_write_output_w(KBD_CMD_ENABLE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Kbd: enable keyboard: no ACK"; + + /* + * Finally, set the typematic rate to maximum. + */ + kbd_write_output_w(KBD_CMD_SET_RATE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Kbd: Set rate: no ACK"; + kbd_write_output_w(0x00); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Kbd: Set rate: no ACK"; + return NULL; +} + +void kbd_interrupt(void) +{ + handle_kbd_event(); +} diff --git a/u-boot/board/mpl/common/kbd.h b/u-boot/board/mpl/common/kbd.h new file mode 100644 index 0000000..229ba61 --- /dev/null +++ b/u-boot/board/mpl/common/kbd.h @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _KBD_H_ +#define _KBD_H_ + +extern int kbd_testc(void); +extern int kbd_getc(void); +extern void kbd_interrupt(void); +extern char *kbd_initialize(void); + +unsigned char kbd_is_init(void); +#define KBD_INTERRUPT 1 +#endif diff --git a/u-boot/board/mpl/common/pci.c b/u-boot/board/mpl/common/pci.c new file mode 100644 index 0000000..f9bb6ab --- /dev/null +++ b/u-boot/board/mpl/common/pci.c @@ -0,0 +1,109 @@ +/*-----------------------------------------------------------------------------+ +| This source code is dual-licensed. You may use it under the terms of +| the GNU General Public License version 2, or under the license below. +| +| This source code has been made available to you by IBM on an AS-IS +| basis. Anyone receiving this source is licensed under IBM +| copyrights to use it in any way he or she deems fit, including +| copying it, modifying it, compiling it, and redistributing it either +| with or without modifications. No license under IBM patents or +| patent applications is to be implied by the copyright license. +| +| Any user of this software should understand that IBM cannot provide +| technical support for this software and will not be responsible for +| any consequences resulting from the use of this software. +| +| Any person who transfers this source code or any derivative work +| must include the IBM copyright notice, this paragraph, and the +| preceding two paragraphs in the transferred software. +| +| COPYRIGHT I B M CORPORATION 1995 +| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M ++-----------------------------------------------------------------------------*/ +/* + * Adapted for PIP405 03.07.01 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * TODO: Clean-up + */ + +#include <common.h> +#include <pci.h> +#include "isa.h" + +#ifdef CONFIG_405GP +#ifdef CONFIG_PCI + +DECLARE_GLOBAL_DATA_PTR; + +#include "piix4_pci.h" +#include "pci_parts.h" + +void pci_pip405_write_regs(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *entry) +{ + struct pci_pip405_config_entry *table; + int i; + + table = (struct pci_pip405_config_entry*) entry->priv[0]; + + for (i=0; table[i].width; i++) + { +#ifdef DEBUG + printf("Reg 0x%02X Value 0x%08lX Width %02d written\n", + table[i].index, table[i].val, table[i].width); +#endif + + switch(table[i].width) + { + case 1: pci_hose_write_config_byte(hose, dev, table[i].index, table[i].val); break; + case 2: pci_hose_write_config_word(hose, dev, table[i].index, table[i].val); break; + case 4: pci_hose_write_config_dword(hose, dev, table[i].index, table[i].val); break; + } + } +} + + +static void pci_pip405_fixup_irq(struct pci_controller *hose, pci_dev_t dev) +{ + unsigned char int_line = 0xff; + unsigned char pin; + /* + * Write pci interrupt line register + */ + if(PCI_DEV(dev)==0) /* Device0 = PPC405 -> skip */ + return; + pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin); + if ((pin == 0) || (pin > 4)) + return; + + int_line = ((PCI_DEV(dev) + (pin-1) + 10) % 4) + 28; + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line); +#ifdef DEBUG + printf("Fixup IRQ: dev %d (%x) int line %d 0x%x\n", + PCI_DEV(dev),dev,int_line,int_line); +#endif +} + +extern void pci_405gp_init(struct pci_controller *hose); + + +static struct pci_controller hose = { + config_table: pci_pip405_config_table, + fixup_irq: pci_pip405_fixup_irq, +}; + + +void pci_init_board(void) +{ + /*we want the ptrs to RAM not flash (ie don't use init list)*/ + hose.fixup_irq = pci_pip405_fixup_irq; + hose.config_table = pci_pip405_config_table; +#ifdef DEBUG + printf("Init PCI: fixup_irq=%p config_table=%p hose=%p\n",pci_pip405_fixup_irq,pci_pip405_config_table,hose); +#endif + pci_405gp_init(&hose); +} + +#endif /* CONFIG_PCI */ +#endif /* CONFIG_405GP */ diff --git a/u-boot/board/mpl/common/pci_parts.h b/u-boot/board/mpl/common/pci_parts.h new file mode 100644 index 0000000..7bca961 --- /dev/null +++ b/u-boot/board/mpl/common/pci_parts.h @@ -0,0 +1,193 @@ + /* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +#ifndef _PCI_PARTS_H_ +#define _PCI_PARTS_H_ + + +/* Board specific file containing: + * - PCI Memory Mapping + * - PCI IO Mapping + * - PCI Interrupt Mapping + */ + +/* PIP405 PCI INT Routing: + * IRQ0 VECTOR + * PIXX4 IDSEL = AD16 INTA# 28 (Function 2 USB is INTD# = 31) + * VGA IDSEL = AD17 INTB# 29 + * SCSI IDSEL = AD18 INTC# 30 + * PC104 IDSEL0 = AD20 INTA# 28 + * PC104 IDSEL1 = AD21 INTB# 29 + * PC104 IDSEL2 = AD22 INTC# 30 + * PC104 IDSEL3 = AD23 INTD# 31 + * + * busdevfunc = EXXX XXXX BBBB BBBB DDDD DFFF RRRR RR00 + * ^ ^ ^ ^ ^ + * 31 23 15 10 7 + * E = Enabled + * B = Bussnumber + * D = Devicenumber (Device0 = AD10) + * F = Functionnumber + * R = Registernumber + * + * Device = (busdevfunc>>11) + 10 + * Vector = devicenumber % 4 + 28 + * + */ +#define PCI_HIGHEST_ON_BOARD_ID 19 +/*#define PCI_DEV_NUMBER(x) (((x>>11) & 0x1f) + 10) */ +#define PCI_IRQ_VECTOR(x) ((PCI_DEV(x) + 10) % 4) + 28 + + +/* PCI Device List for PIP405 */ + +/* Mapping: + * +-------------+------------+------------+--------------------------------+ + * ¦ PCI MemAddr | PCI IOAddr | Local Addr | Device / Function | + * +-------------+------------+------------+--------------------------------+ + * | 0x00000000 | | 0xA0000000 | ISA Memory (hard wired) | + * | 0x00FFFFFF | | 0xA0FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + * | | 0x00000000 | 0xE8000000 | ISA IO (hard wired) | + * | | 0x0000FFFF | 0xE800FFFF | | + * +-------------+------------+------------+--------------------------------+ + * | 0x80000000 | | 0x80000000 | VGA Controller Memory | + * | 0x80FFFFFF | | 0x80FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + * | 0x81000000 | | 0x81000000 | SCSI Controller Memory | + * | 0x81FFFFFF | | 0x81FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + */ + +struct pci_pip405_config_entry { + int index; /* address */ + unsigned long val; /* value */ + int width; /* data size */ +}; + +extern void pci_pip405_write_regs(struct pci_controller *, + pci_dev_t, + struct pci_config_table *); + +/* PIIX4 ISA Bridge Function 0 */ +static struct pci_pip405_config_entry piix4_isa_bridge_f0[] = { + {PCI_CFG_PIIX4_SERIRQ, 0xD0, 1}, /* enable Continous SERIRQ Pin */ + {PCI_CFG_PIIX4_GENCFG, 0x00018041, 4}, /* enable SERIRQs, ISA, PNP, GPI11 */ + {PCI_CFG_PIIX4_TOM, 0xFE, 1}, /* Top of Memory */ + {PCI_CFG_PIIX4_XBCS, 0x02C4, 2}, /* disable all peri CS */ + {PCI_CFG_PIIX4_RTCCFG, 0x21, 1}, /* enable RTC */ +#if defined(CONFIG_PIP405) + {PCI_CFG_PIIX4_MBDMA, 0x82, 1}, /* set MBDMA0 to DMA 2 */ + {PCI_CFG_PIIX4_MBDMA+1, 0x83, 1}, /* set MBDMA1 to DMA 3 */ +#endif + {PCI_CFG_PIIX4_DLC, 0x0, 1}, /* disable passive release feature */ + { } /* end of device table */ +}; + +/* PIIX4 IDE Controller Function 1 */ +static struct pci_pip405_config_entry piix4_ide_cntrl_f1[] = { + {PCI_CFG_PIIX4_BMIBA, 0x0001000, 4}, /* set BMI to a valid address */ + {PCI_COMMAND, 0x0001, 2}, /* enable IO access */ +#if !defined(CONFIG_MIP405T) + {PCI_CFG_PIIX4_IDETIM, 0x80008000, 4}, /* enable Both IDE channels */ +#else + {PCI_CFG_PIIX4_IDETIM, 0x00008000, 4}, /* enable IDE channel0 */ +#endif + { } /* end of device table */ +}; + +/* PIIX4 USB Controller Function 2 */ +static struct pci_pip405_config_entry piix4_usb_cntrl_f2[] = { +#if !defined(CONFIG_MIP405T) + {PCI_INTERRUPT_LINE, 31, 1}, /* Int vector = 31 */ + {PCI_BASE_ADDRESS_4, 0x0000E001, 4}, /* Set IO Address to 0xe000 to 0xe01F */ + {PCI_LATENCY_TIMER, 0x80, 1}, /* Latency Timer 0x80 */ + {0xC0, 0x2000, 2}, /* Legacy support */ + {PCI_COMMAND, 0x0005, 2}, /* enable IO access and Master */ +#endif + { } /* end of device table */ +}; + +/* PIIX4 Power Management Function 3 */ +static struct pci_pip405_config_entry piix4_pmm_cntrl_f3[] = { + {PCI_CFG_PIIX4_PMBA, 0x00004000, 4}, /* set PMBA to "valid" value */ + {PCI_CFG_PIIX4_SMBBA, 0x00005000, 4}, /* set SMBBA to "valid" value */ + {PCI_CFG_PIIX4_PMMISC, 0x01, 1}, /* enable PMBA IO access */ + {PCI_COMMAND, 0x0001, 2}, /* enable IO access */ + { } /* end of device table */ +}; +/* PPC405 Dummy only used to prevent autosetup on this host bridge */ +static struct pci_pip405_config_entry ppc405_dummy[] = { + { } /* end of device table */ +}; + +void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *entry); + + +static struct pci_config_table pci_pip405_config_table[]={ + {PCI_VENDOR_ID_IBM, /* 405 dummy */ + PCI_DEVICE_ID_IBM_405GP, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 0, + pci_pip405_write_regs, {(unsigned long) ppc405_dummy}}, + + {PCI_VENDOR_ID_INTEL, /* PIIX4 ISA Bridge Function 0 */ + PCI_DEVICE_ID_INTEL_82371AB_0, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 0, + pci_pip405_write_regs, {(unsigned long) piix4_isa_bridge_f0}}, + + {PCI_VENDOR_ID_INTEL, /* PIIX4 IDE Controller Function 1 */ + PCI_DEVICE_ID_INTEL_82371AB, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 1, + pci_pip405_write_regs, {(unsigned long) piix4_ide_cntrl_f1}}, + + {PCI_VENDOR_ID_INTEL, /* PIIX4 USB Controller Function 2 */ + PCI_DEVICE_ID_INTEL_82371AB_2, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 2, + pci_pip405_write_regs, {(unsigned long) piix4_usb_cntrl_f2}}, + + {PCI_VENDOR_ID_INTEL, /* PIIX4 USB Controller Function 3 */ + PCI_DEVICE_ID_INTEL_82371AB_3, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 3, + pci_pip405_write_regs, {(unsigned long) piix4_pmm_cntrl_f3}}, + + {PCI_ANY_ID, + PCI_ANY_ID, + PCI_CLASS_DISPLAY_VGA, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_405gp_setup_vga}, + + {PCI_ANY_ID, + PCI_ANY_ID, + PCI_CLASS_NOT_DEFINED_VGA, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_405gp_setup_vga}, + + { } +}; +#endif /* _PCI_PARTS_H_ */ diff --git a/u-boot/board/mpl/common/piix4_pci.h b/u-boot/board/mpl/common/piix4_pci.h new file mode 100644 index 0000000..0ff802e --- /dev/null +++ b/u-boot/board/mpl/common/piix4_pci.h @@ -0,0 +1,165 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#ifndef _PIIX4_PCI_H +#define _PIIX4_PCI_H + +/*************************************************************************** +* Defines PIIX4 Config Registers +****************************************************************************/ + +/* Function 0 ISA Bridge */ +#define PCI_CFG_PIIX4_IORT 0x4C /* 8 bit ISA Recovery Timer Reg (default 0x4D) */ +#define PCI_CFG_PIIX4_XBCS 0x4E /* 16 bit XBus Chip select reg (default 0x0003) */ +#define PCI_CFG_PIIX4_PIRQC 0x60 /* PCI IRQ Route Register 4 x 8bit (default )*/ +#define PCI_CFG_PIIX4_SERIRQ 0x64 +#define PCI_CFG_PIIX4_TOM 0x69 +#define PCI_CFG_PIIX4_MSTAT 0x6A +#define PCI_CFG_PIIX4_MBDMA 0x76 +#define PCI_CFG_PIIX4_APICBS 0x80 +#define PCI_CFG_PIIX4_DLC 0x82 +#define PCI_CFG_PIIX4_PDMACFG 0x90 +#define PCI_CFG_PIIX4_DDMABS 0x92 +#define PCI_CFG_PIIX4_GENCFG 0xB0 +#define PCI_CFG_PIIX4_RTCCFG 0xCB + +/* IO Addresses */ +#define PIIX4_ISA_DMA1_CH0BA 0x00 +#define PIIX4_ISA_DMA1_CH0CA 0x01 +#define PIIX4_ISA_DMA1_CH1BA 0x02 +#define PIIX4_ISA_DMA1_CH1CA 0x03 +#define PIIX4_ISA_DMA1_CH2BA 0x04 +#define PIIX4_ISA_DMA1_CH2CA 0x05 +#define PIIX4_ISA_DMA1_CH3BA 0x06 +#define PIIX4_ISA_DMA1_CH3CA 0x07 +#define PIIX4_ISA_DMA1_CMDST 0x08 +#define PIIX4_ISA_DMA1_REQ 0x09 +#define PIIX4_ISA_DMA1_WSBM 0x0A +#define PIIX4_ISA_DMA1_CH_MOD 0x0B +#define PIIX4_ISA_DMA1_CLR_PT 0x0C +#define PIIX4_ISA_DMA1_M_CLR 0x0D +#define PIIX4_ISA_DMA1_CLR_M 0x0E +#define PIIX4_ISA_DMA1_RWAMB 0x0F + +#define PIIX4_ISA_DMA2_CH0BA 0xC0 +#define PIIX4_ISA_DMA2_CH0CA 0xC1 +#define PIIX4_ISA_DMA2_CH1BA 0xC2 +#define PIIX4_ISA_DMA2_CH1CA 0xC3 +#define PIIX4_ISA_DMA2_CH2BA 0xC4 +#define PIIX4_ISA_DMA2_CH2CA 0xC5 +#define PIIX4_ISA_DMA2_CH3BA 0xC6 +#define PIIX4_ISA_DMA2_CH3CA 0xC7 +#define PIIX4_ISA_DMA2_CMDST 0xD0 +#define PIIX4_ISA_DMA2_REQ 0xD2 +#define PIIX4_ISA_DMA2_WSBM 0xD4 +#define PIIX4_ISA_DMA2_CH_MOD 0xD6 +#define PIIX4_ISA_DMA2_CLR_PT 0xD8 +#define PIIX4_ISA_DMA2_M_CLR 0xDA +#define PIIX4_ISA_DMA2_CLR_M 0xDC +#define PIIX4_ISA_DMA2_RWAMB 0xDE + +#define PIIX4_ISA_INT1_ICW1 0x20 +#define PIIX4_ISA_INT1_OCW2 0x20 +#define PIIX4_ISA_INT1_OCW3 0x20 +#define PIIX4_ISA_INT1_ICW2 0x21 +#define PIIX4_ISA_INT1_ICW3 0x21 +#define PIIX4_ISA_INT1_ICW4 0x21 +#define PIIX4_ISA_INT1_OCW1 0x21 + +#define PIIX4_ISA_INT1_ELCR 0x4D0 + +#define PIIX4_ISA_INT2_ICW1 0xA0 +#define PIIX4_ISA_INT2_OCW2 0xA0 +#define PIIX4_ISA_INT2_OCW3 0xA0 +#define PIIX4_ISA_INT2_ICW2 0xA1 +#define PIIX4_ISA_INT2_ICW3 0xA1 +#define PIIX4_ISA_INT2_ICW4 0xA1 +#define PIIX4_ISA_INT2_OCW1 0xA1 +#define PIIX4_ISA_INT2_IMR 0xA1 /* read only */ + +#define PIIX4_ISA_INT2_ELCR 0x4D1 + +#define PIIX4_ISA_TMR0_CNT_ST 0x40 +#define PIIX4_ISA_TMR1_CNT_ST 0x41 +#define PIIX4_ISA_TMR2_CNT_ST 0x42 +#define PIIX4_ISA_TMR_TCW 0x43 + +#define PIIX4_ISA_RST_XBUS 0x60 + +#define PIIX4_ISA_NMI_CNT_ST 0x61 +#define PIIX4_ISA_NMI_ENABLE 0x70 + +#define PIIX4_ISA_RTC_INDEX 0x70 +#define PIIX4_ISA_RTC_DATA 0x71 +#define PIIX4_ISA_RTCEXT_IND 0x70 +#define PIIX4_ISA_RTCEXT_DATA 0x71 + +#define PIIX4_ISA_DMA1_CH2LPG 0x81 +#define PIIX4_ISA_DMA1_CH3LPG 0x82 +#define PIIX4_ISA_DMA1_CH1LPG 0x83 +#define PIIX4_ISA_DMA1_CH0LPG 0x87 +#define PIIX4_ISA_DMA2_CH2LPG 0x89 +#define PIIX4_ISA_DMA2_CH3LPG 0x8A +#define PIIX4_ISA_DMA2_CH1LPG 0x8B +#define PIIX4_ISA_DMA2_LPGRFR 0x8F + +#define PIIX4_ISA_PORT_92 0x92 + +#define PIIX4_ISA_APM_CONTRL 0xB2 +#define PIIX4_ISA_APM_STATUS 0xB3 + +#define PIIX4_ISA_COCPU_ERROR 0xF0 + +/* Function 1 IDE Controller */ +#define PCI_CFG_PIIX4_BMIBA 0x20 +#define PCI_CFG_PIIX4_IDETIM 0x40 +#define PCI_CFG_PIIX4_SIDETIM 0x44 +#define PCI_CFG_PIIX4_UDMACTL 0x48 +#define PCI_CFG_PIIX4_UDMATIM 0x4A + +/* Function 2 USB Controller */ +#define PCI_CFG_PIIX4_SBRNUM 0x60 +#define PCI_CFG_PIIX4_LEGSUP 0xC0 + +/* Function 3 Power Management */ +#define PCI_CFG_PIIX4_PMBA 0x40 +#define PCI_CFG_PIIX4_CNTA 0x44 +#define PCI_CFG_PIIX4_CNTB 0x48 +#define PCI_CFG_PIIX4_GPICTL 0x4C +#define PCI_CFG_PIIX4_DEVRESD 0x50 +#define PCI_CFG_PIIX4_DEVACTA 0x54 +#define PCI_CFG_PIIX4_DEVACTB 0x58 +#define PCI_CFG_PIIX4_DEVRESA 0x5C +#define PCI_CFG_PIIX4_DEVRESB 0x60 +#define PCI_CFG_PIIX4_DEVRESC 0x64 +#define PCI_CFG_PIIX4_DEVRESE 0x68 +#define PCI_CFG_PIIX4_DEVRESF 0x6C +#define PCI_CFG_PIIX4_DEVRESG 0x70 +#define PCI_CFG_PIIX4_DEVRESH 0x74 +#define PCI_CFG_PIIX4_DEVRESI 0x78 +#define PCI_CFG_PIIX4_PMMISC 0x80 +#define PCI_CFG_PIIX4_SMBBA 0x90 + + +#endif diff --git a/u-boot/board/mpl/common/usb_uhci.c b/u-boot/board/mpl/common/usb_uhci.c new file mode 100644 index 0000000..a009437 --- /dev/null +++ b/u-boot/board/mpl/common/usb_uhci.c @@ -0,0 +1,1169 @@ +/* + * Part of this code has been derived from linux: + * Universal Host Controller Interface driver for USB (take II). + * + * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar) + * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) + * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) + * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) + * (c) 2000 Yggdrasil Computing, Inc. (port of new PCI interface support + * from usb-ohci.c by Adam Richter, adam@yggdrasil.com). + * (C) 2000 David Brownell, david-b@pacbell.net (usb-ohci.c) + * + * HW-initalization based on material of + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Randy Dunlap + * (C) Copyright 1999 Gregory P. Smith + * + * + * Adapted for U-Boot: + * (C) Copyright 2001 Denis Peter, MPL AG Switzerland + * + * 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 + * + * + */ + +/********************************************************************** + * How it works: + * ------------- + * The framelist / Transfer descriptor / Queue Heads are similar like + * in the linux usb_uhci.c. + * + * During initialization, the following skeleton is allocated in init_skel: + * + * framespecific | common chain + * + * framelist[] + * [ 0 ]-----> TD ---------\ + * [ 1 ]-----> TD ----------> TD ------> QH -------> QH -------> QH ---> NULL + * ... TD ---------/ + * [1023]-----> TD --------/ + * + * ^^ ^^ ^^ ^^ ^^ + * 7 TDs for 1 TD for Start of Start of End Chain + * INT (2-128ms) 1ms-INT CTRL Chain BULK Chain + * + * + * Since this is a bootloader, the isochronous transfer descriptor have been removed. + * + * Interrupt Transfers. + * -------------------- + * For Interupt transfers USB_MAX_TEMP_INT_TD Transfer descriptor are available. They + * will be inserted after the appropriate (depending the interval setting) skeleton TD. + * If an interrupt has been detected the dev->irqhandler is called. The status and number + * of transfered bytes is stored in dev->irq_status resp. dev->irq_act_len. If the + * dev->irqhandler returns 0, the interrupt TD is removed and disabled. If an 1 is returned, + * the interrupt TD will be reactivated. + * + * Control Transfers + * ----------------- + * Control Transfers are issued by filling the tmp_td with the appropriate data and connect + * them to the qh_cntrl queue header. Before other control/bulk transfers can be issued, + * the programm has to wait for completion. This does not allows asynchronous data transfer. + * + * Bulk Transfers + * -------------- + * Bulk Transfers are issued by filling the tmp_td with the appropriate data and connect + * them to the qh_bulk queue header. Before other control/bulk transfers can be issued, + * the programm has to wait for completion. This does not allows asynchronous data transfer. + * + * + */ + +#include <common.h> +#include <pci.h> + +#ifdef CONFIG_USB_UHCI + +#include <usb.h> +#include "usb_uhci.h" + +#define USB_MAX_TEMP_TD 128 /* number of temporary TDs for bulk and control transfers */ +#define USB_MAX_TEMP_INT_TD 32 /* number of temporary TDs for Interrupt transfers */ + + +#undef USB_UHCI_DEBUG + +#ifdef USB_UHCI_DEBUG +#define USB_UHCI_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define USB_UHCI_PRINTF(fmt,args...) +#endif + + +static int irqvec = -1; /* irq vector, if -1 uhci is stopped / reseted */ +unsigned int usb_base_addr; /* base address */ + +static uhci_td_t td_int[8]; /* Interrupt Transfer descriptors */ +static uhci_qh_t qh_cntrl; /* control Queue Head */ +static uhci_qh_t qh_bulk; /* bulk Queue Head */ +static uhci_qh_t qh_end; /* end Queue Head */ +static uhci_td_t td_last; /* last TD (linked with end chain) */ + +/* temporary tds */ +static uhci_td_t tmp_td[USB_MAX_TEMP_TD]; /* temporary bulk/control td's */ +static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD]; /* temporary interrupt td's */ + +static unsigned long framelist[1024] __attribute__ ((aligned (0x1000))); /* frame list */ + +static struct virt_root_hub rh; /* struct for root hub */ + +/********************************************************************** + * some forward decleration + */ +int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len,struct devrequest *setup); + +/* fill a td with the approproiate data. Link, status, info and buffer + * are used by the USB controller itselfes, dev is used to identify the + * "connected" device + */ +void usb_fill_td(uhci_td_t* td,unsigned long link,unsigned long status, + unsigned long info, unsigned long buffer, unsigned long dev) +{ + td->link=swap_32(link); + td->status=swap_32(status); + td->info=swap_32(info); + td->buffer=swap_32(buffer); + td->dev_ptr=dev; +} + +/* fill a qh with the approproiate data. Head and element are used by the USB controller + * itselfes. As soon as a valid dev_ptr is filled, a td chain is connected to the qh. + * Please note, that after completion of the td chain, the entry element is removed / + * marked invalid by the USB controller. + */ +void usb_fill_qh(uhci_qh_t* qh,unsigned long head,unsigned long element) +{ + qh->head=swap_32(head); + qh->element=swap_32(element); + qh->dev_ptr=0L; +} + +/* get the status of a td->status + */ +unsigned long usb_uhci_td_stat(unsigned long status) +{ + unsigned long result=0; + result |= (status & TD_CTRL_NAK) ? USB_ST_NAK_REC : 0; + result |= (status & TD_CTRL_STALLED) ? USB_ST_STALLED : 0; + result |= (status & TD_CTRL_DBUFERR) ? USB_ST_BUF_ERR : 0; + result |= (status & TD_CTRL_BABBLE) ? USB_ST_BABBLE_DET : 0; + result |= (status & TD_CTRL_CRCTIMEO) ? USB_ST_CRC_ERR : 0; + result |= (status & TD_CTRL_BITSTUFF) ? USB_ST_BIT_ERR : 0; + result |= (status & TD_CTRL_ACTIVE) ? USB_ST_NOT_PROC : 0; + return result; +} + +/* get the status and the transfered len of a td chain. + * called from the completion handler + */ +int usb_get_td_status(uhci_td_t *td,struct usb_device *dev) +{ + unsigned long temp,info; + unsigned long stat; + uhci_td_t *mytd=td; + + if(dev->devnum==rh.devnum) + return 0; + dev->act_len=0; + stat=0; + do { + temp=swap_32((unsigned long)mytd->status); + stat=usb_uhci_td_stat(temp); + info=swap_32((unsigned long)mytd->info); + if(((info & 0xff)!= USB_PID_SETUP) && + (((info >> 21) & 0x7ff)!= 0x7ff) && + (temp & 0x7FF)!=0x7ff) + { /* if not setup and not null data pack */ + dev->act_len+=(temp & 0x7FF) + 1; /* the transfered len is act_len + 1 */ + } + if(stat) { /* status no ok */ + dev->status=stat; + return -1; + } + temp=swap_32((unsigned long)mytd->link); + mytd=(uhci_td_t *)(temp & 0xfffffff0); + }while((temp & 0x1)==0); /* process all TDs */ + dev->status=stat; + return 0; /* Ok */ +} + + +/*------------------------------------------------------------------- + * LOW LEVEL STUFF + * assembles QHs und TDs for control, bulk and iso + *-------------------------------------------------------------------*/ + +/* Submits a control message. That is a Setup, Data and Status transfer. + * Routine does not wait for completion. + */ +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len,struct devrequest *setup) +{ + unsigned long destination, status; + int maxsze = usb_maxpacket(dev, pipe); + unsigned long dataptr; + int len; + int pktsze; + int i=0; + + if (!maxsze) { + USB_UHCI_PRINTF("uhci_submit_control_urb: pipesize for pipe %lx is zero\n", pipe); + return -1; + } + if(((pipe>>8)&0x7f)==rh.devnum) { + /* this is the root hub -> redirect it */ + return uhci_submit_rh_msg(dev,pipe,buffer,transfer_len,setup); + } + USB_UHCI_PRINTF("uhci_submit_control start len %x, maxsize %x\n",transfer_len,maxsze); + /* The "pipe" thing contains the destination in bits 8--18 */ + destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; /* Setup stage */ + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27); + /* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD); */ + /* Build the TD for the control request, try forever, 8 bytes of data */ + usb_fill_td(&tmp_td[i],UHCI_PTR_TERM ,status, destination | (7 << 21),(unsigned long)setup,(unsigned long)dev); +#if 0 + { + char *sp=(char *)setup; + printf("SETUP to pipe %lx: %x %x %x %x %x %x %x %x\n", pipe, + sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]); + } +#endif + dataptr = (unsigned long)buffer; + len=transfer_len; + + /* If direction is "send", change the frame from SETUP (0x2D) + to OUT (0xE1). Else change it from SETUP to IN (0x69). */ + destination = (pipe & PIPE_DEVEP_MASK) | ((pipe & USB_DIR_IN)==0 ? USB_PID_OUT : USB_PID_IN); + while (len > 0) { + /* data stage */ + pktsze = len; + i++; + if (pktsze > maxsze) + pktsze = maxsze; + destination ^= 1 << TD_TOKEN_TOGGLE; /* toggle DATA0/1 */ + usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, destination | ((pktsze - 1) << 21),dataptr,(unsigned long)dev); /* Status, pktsze bytes of data */ + tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]); + + dataptr += pktsze; + len -= pktsze; + } + + /* Build the final TD for control status */ + /* It's only IN if the pipe is out AND we aren't expecting data */ + + destination &= ~UHCI_PID; + if (((pipe & USB_DIR_IN)==0) || (transfer_len == 0)) + destination |= USB_PID_IN; + else + destination |= USB_PID_OUT; + destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ + i++; + status &=~TD_CTRL_SPD; + /* no limit on errors on final packet , 0 bytes of data */ + usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21),0,(unsigned long)dev); + tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]); /* queue status td */ + /* usb_show_td(i+1);*/ + USB_UHCI_PRINTF("uhci_submit_control end (%d tmp_tds used)\n",i); + /* first mark the control QH element terminated */ + qh_cntrl.element=0xffffffffL; + /* set qh active */ + qh_cntrl.dev_ptr=(unsigned long)dev; + /* fill in tmp_td_chain */ + qh_cntrl.element=swap_32((unsigned long)&tmp_td[0]); + return 0; +} + +/*------------------------------------------------------------------- + * Prepare TDs for bulk transfers. + */ +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len) +{ + unsigned long destination, status,info; + unsigned long dataptr; + int maxsze = usb_maxpacket(dev, pipe); + int len; + int i=0; + + if(transfer_len < 0) { + printf("Negative transfer length in submit_bulk\n"); + return -1; + } + if (!maxsze) + return -1; + /* The "pipe" thing contains the destination in bits 8--18. */ + destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27); + /* ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); */ + /* Build the TDs for the bulk request */ + len = transfer_len; + dataptr = (unsigned long)buffer; + do { + int pktsze = len; + if (pktsze > maxsze) + pktsze = maxsze; + /* pktsze bytes of data */ + info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) | + (usb_gettoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); + + if((len-pktsze)==0) + status |= TD_CTRL_IOC; /* last one generates INT */ + + usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, info,dataptr,(unsigned long)dev); /* Status, pktsze bytes of data */ + if(i>0) + tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]); + i++; + dataptr += pktsze; + len -= pktsze; + usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); + } while (len > 0); + /* first mark the bulk QH element terminated */ + qh_bulk.element=0xffffffffL; + /* set qh active */ + qh_bulk.dev_ptr=(unsigned long)dev; + /* fill in tmp_td_chain */ + qh_bulk.element=swap_32((unsigned long)&tmp_td[0]); + return 0; +} + + +/* search a free interrupt td + */ +uhci_td_t *uhci_alloc_int_td(void) +{ + int i; + for(i=0;i<USB_MAX_TEMP_INT_TD;i++) { + if(tmp_int_td[i].dev_ptr==0) /* no device assigned -> free TD */ + return &tmp_int_td[i]; + } + return NULL; +} + +#if 0 +void uhci_show_temp_int_td(void) +{ + int i; + for(i=0;i<USB_MAX_TEMP_INT_TD;i++) { + if((tmp_int_td[i].dev_ptr&0x01)!=0x1L) /* no device assigned -> free TD */ + printf("temp_td %d is assigned to dev %lx\n",i,tmp_int_td[i].dev_ptr); + } + printf("all others temp_tds are free\n"); +} +#endif +/*------------------------------------------------------------------- + * submits USB interrupt (ie. polling ;-) + */ +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len, int interval) +{ + int nint, n; + unsigned long status, destination; + unsigned long info,tmp; + uhci_td_t *mytd; + if (interval < 0 || interval >= 256) + return -1; + + if (interval == 0) + nint = 0; + else { + for (nint = 0, n = 1; nint <= 8; nint++, n += n) /* round interval down to 2^n */ + { + if(interval < n) { + interval = n / 2; + break; + } + } + nint--; + } + + USB_UHCI_PRINTF("Rounded interval to %i, chain %i\n", interval, nint); + mytd=uhci_alloc_int_td(); + if(mytd==NULL) { + printf("No free INT TDs found\n"); + return -1; + } + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27); +/* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); +*/ + + destination =(pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe) | (((transfer_len - 1) & 0x7ff) << 21); + + info = destination | (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE); + tmp = swap_32(td_int[nint].link); + usb_fill_td(mytd,tmp,status, info,(unsigned long)buffer,(unsigned long)dev); + /* Link it */ + tmp = swap_32((unsigned long)mytd); + td_int[nint].link=tmp; + + usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); + + return 0; +} + +/********************************************************************** + * Low Level functions + */ + + +void reset_hc(void) +{ + + /* Global reset for 100ms */ + out16r( usb_base_addr + USBPORTSC1,0x0204); + out16r( usb_base_addr + USBPORTSC2,0x0204); + out16r( usb_base_addr + USBCMD,USBCMD_GRESET | USBCMD_RS); + /* Turn off all interrupts */ + out16r(usb_base_addr + USBINTR,0); + wait_ms(50); + out16r( usb_base_addr + USBCMD,0); + wait_ms(10); +} + +void start_hc(void) +{ + int timeout = 1000; + + while(in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) { + if (!--timeout) { + printf("USBCMD_HCRESET timed out!\n"); + break; + } + } + /* Turn on all interrupts */ + out16r(usb_base_addr + USBINTR,USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP); + /* Start at frame 0 */ + out16r(usb_base_addr + USBFRNUM,0); + /* set Framebuffer base address */ + out32r(usb_base_addr+USBFLBASEADD,(unsigned long)&framelist); + /* Run and mark it configured with a 64-byte max packet */ + out16r(usb_base_addr + USBCMD,USBCMD_RS | USBCMD_CF | USBCMD_MAXP); +} + +/* Initialize the skeleton + */ +void usb_init_skel(void) +{ + unsigned long temp; + int n; + + for(n=0;n<USB_MAX_TEMP_INT_TD;n++) + tmp_int_td[n].dev_ptr=0L; /* no devices connected */ + /* last td */ + usb_fill_td(&td_last,UHCI_PTR_TERM,TD_CTRL_IOC ,0,0,0L); + /* usb_fill_td(&td_last,UHCI_PTR_TERM,0,0,0); */ + /* End Queue Header */ + usb_fill_qh(&qh_end,UHCI_PTR_TERM,(unsigned long)&td_last); + /* Bulk Queue Header */ + temp=(unsigned long)&qh_end; + usb_fill_qh(&qh_bulk,temp | UHCI_PTR_QH,UHCI_PTR_TERM); + /* Control Queue Header */ + temp=(unsigned long)&qh_bulk; + usb_fill_qh(&qh_cntrl, temp | UHCI_PTR_QH,UHCI_PTR_TERM); + /* 1ms Interrupt td */ + temp=(unsigned long)&qh_cntrl; + usb_fill_td(&td_int[0],temp | UHCI_PTR_QH,0,0,0,0L); + temp=(unsigned long)&td_int[0]; + for(n=1; n<8; n++) + usb_fill_td(&td_int[n],temp,0,0,0,0L); + for (n = 0; n < 1024; n++) { + /* link all framelist pointers to one of the interrupts */ + int m, o; + if ((n&127)==127) + framelist[n]= swap_32((unsigned long)&td_int[0]); + else + for (o = 1, m = 2; m <= 128; o++, m += m) + if ((n & (m - 1)) == ((m - 1) / 2)) + framelist[n]= swap_32((unsigned long)&td_int[o]); + } +} + +/* check the common skeleton for completed transfers, and update the status + * of the "connected" device. Called from the IRQ routine. + */ +void usb_check_skel(void) +{ + struct usb_device *dev; + /* start with the control qh */ + if(qh_cntrl.dev_ptr!=0) /* it's a device assigned check if this caused IRQ */ + { + dev=(struct usb_device *)qh_cntrl.dev_ptr; + usb_get_td_status(&tmp_td[0],dev); /* update status */ + if(!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */ + qh_cntrl.dev_ptr=0; + } + } + /* now process the bulk */ + if(qh_bulk.dev_ptr!=0) /* it's a device assigned check if this caused IRQ */ + { + dev=(struct usb_device *)qh_bulk.dev_ptr; + usb_get_td_status(&tmp_td[0],dev); /* update status */ + if(!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */ + qh_bulk.dev_ptr=0; + } + } +} + +/* check the interrupt chain, ubdate the status of the appropriate device, + * call the appropriate irqhandler and reactivate the TD if the irqhandler + * returns with 1 + */ +void usb_check_int_chain(void) +{ + int i,res; + unsigned long link,status; + struct usb_device *dev; + uhci_td_t *td,*prevtd; + + for(i=0;i<8;i++) { + prevtd = &td_int[i]; /* the first previous td is the skeleton td */ + link=swap_32(td_int[i].link) & 0xfffffff0; /* next in chain */ + td=(uhci_td_t *)link; /* assign it */ + /* all interrupt TDs are finally linked to the td_int[0]. + * so we process all until we find the td_int[0]. + * if int0 chain points to a QH, we're also done + */ + while(((i>0) && (link != (unsigned long)&td_int[0])) || + ((i==0) && !(swap_32(td->link) & UHCI_PTR_QH))) + { + /* check if a device is assigned with this td */ + status=swap_32(td->status); + if((td->dev_ptr!=0L) && !(status & TD_CTRL_ACTIVE)) { + /* td is not active and a device is assigned -> call irqhandler */ + dev=(struct usb_device *)td->dev_ptr; + dev->irq_act_len=((status & 0x7FF)==0x7FF) ? 0 : (status & 0x7FF) + 1; /* transfered length */ + dev->irq_status=usb_uhci_td_stat(status); /* get status */ + res=dev->irq_handle(dev); /* call irqhandler */ + if(res==1) { + /* reactivate */ + status|=TD_CTRL_ACTIVE; + td->status=swap_32(status); + prevtd=td; /* previous td = this td */ + } + else { + prevtd->link=td->link; /* link previous td directly to the nex td -> unlinked */ + /* remove device pointer */ + td->dev_ptr=0L; + } + } /* if we call the irq handler */ + link=swap_32(td->link) & 0xfffffff0; /* next in chain */ + td=(uhci_td_t *)link; /* assign it */ + } /* process all td in this int chain */ + } /* next interrupt chain */ +} + + +/* usb interrupt service routine. + */ +void handle_usb_interrupt(void) +{ + unsigned short status; + + /* + * Read the interrupt status, and write it back to clear the + * interrupt cause + */ + + status = in16r(usb_base_addr + USBSTS); + + if (!status) /* shared interrupt, not mine */ + return; + if (status != 1) { + /* remove host controller halted state */ + if ((status&0x20) && ((in16r(usb_base_addr+USBCMD) && USBCMD_RS)==0)) { + out16r(usb_base_addr + USBCMD, USBCMD_RS | in16r(usb_base_addr + USBCMD)); + } + } + usb_check_int_chain(); /* call interrupt handlers for int tds */ + usb_check_skel(); /* call completion handler for common transfer routines */ + out16r(usb_base_addr+USBSTS,status); +} + + +/* init uhci + */ +int usb_lowlevel_init(void) +{ + unsigned char temp; + int busdevfunc; + + busdevfunc=pci_find_device(USB_UHCI_VEND_ID,USB_UHCI_DEV_ID,0); /* get PCI Device ID */ + if(busdevfunc==-1) { + printf("Error USB UHCI (%04X,%04X) not found\n",USB_UHCI_VEND_ID,USB_UHCI_DEV_ID); + return -1; + } + pci_read_config_byte(busdevfunc,PCI_INTERRUPT_LINE,&temp); + irqvec = temp; + irq_free_handler(irqvec); + USB_UHCI_PRINTF("Interrupt Line = %d, is %d\n",irqvec); + pci_read_config_byte(busdevfunc,PCI_INTERRUPT_PIN,&temp); + USB_UHCI_PRINTF("Interrupt Pin = %ld\n",temp); + pci_read_config_dword(busdevfunc,PCI_BASE_ADDRESS_4,&usb_base_addr); + USB_UHCI_PRINTF("IO Base Address = 0x%lx\n",usb_base_addr); + usb_base_addr&=0xFFFFFFF0; + usb_base_addr+=CONFIG_SYS_ISA_IO_BASE_ADDRESS; + rh.devnum = 0; + usb_init_skel(); + reset_hc(); + start_hc(); + irq_install_handler(irqvec, (interrupt_handler_t *)handle_usb_interrupt, NULL); + return 0; +} + +/* stop uhci + */ +int usb_lowlevel_stop(void) +{ + if(irqvec==-1) + return 1; + irq_free_handler(irqvec); + reset_hc(); + irqvec = -1; + return 0; +} + +/******************************************************************************************* + * Virtual Root Hub + * Since the uhci does not have a real HUB, we simulate one ;-) + */ +#undef USB_RH_DEBUG + +#ifdef USB_RH_DEBUG +#define USB_RH_PRINTF(fmt,args...) printf (fmt ,##args) +static void usb_display_wValue(unsigned short wValue,unsigned short wIndex); +static void usb_display_Req(unsigned short req); +#else +#define USB_RH_PRINTF(fmt,args...) +static void usb_display_wValue(unsigned short wValue,unsigned short wIndex) {} +static void usb_display_Req(unsigned short req) {} +#endif + +static unsigned char root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, /* __u16 bcdUSB; v1.0 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x01, /* __u8 iManufacturer; */ + 0x00, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static unsigned char root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + + +static unsigned char root_hub_hub_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x29, /* __u8 bDescriptorType; Hub-descriptor */ + 0x02, /* __u8 bNbrPorts; */ + 0x00, /* __u16 wHubCharacteristics; */ + 0x00, + 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ + 0x00, /* __u8 bHubContrCurrent; 0 mA */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ +}; + +static unsigned char root_hub_str_index0[] = +{ + 0x04, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 0x09, /* __u8 lang ID */ + 0x04, /* __u8 lang ID */ +}; + +static unsigned char root_hub_str_index1[] = +{ + 28, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 'U', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'C', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'I', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'R', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'u', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'b', /* __u8 Unicode */ + 0, /* __u8 Unicode */ +}; + + +/* + * Root Hub Control Pipe (interrupt Pipes are not supported) + */ + + +int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len,struct devrequest *cmd) +{ + void *data = buffer; + int leni = transfer_len; + int len = 0; + int status = 0; + int stat = 0; + int i; + + unsigned short cstatus; + + unsigned short bmRType_bReq; + unsigned short wValue; + unsigned short wIndex; + unsigned short wLength; + + if (usb_pipeint(pipe)) { + printf("Root-Hub submit IRQ: NOT implemented\n"); +#if 0 + uhci->rh.urb = urb; + uhci->rh.send = 1; + uhci->rh.interval = urb->interval; + rh_init_int_timer (urb); +#endif + return 0; + } + bmRType_bReq = cmd->requesttype | cmd->request << 8; + wValue = swap_16(cmd->value); + wIndex = swap_16(cmd->index); + wLength = swap_16(cmd->length); + usb_display_Req(bmRType_bReq); + for (i = 0; i < 8; i++) + rh.c_p_r[i] = 0; + USB_RH_PRINTF("Root-Hub: adr: %2x cmd(%1x): %02x%02x %04x %04x %04x\n", + dev->devnum, 8, cmd->requesttype,cmd->request, wValue, wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(unsigned short *) data = swap_16(1); + len=2; + break; + case RH_GET_STATUS | RH_INTERFACE: + *(unsigned short *) data = swap_16(0); + len=2; + break; + case RH_GET_STATUS | RH_ENDPOINT: + *(unsigned short *) data = swap_16(0); + len=2; + break; + case RH_GET_STATUS | RH_CLASS: + *(unsigned long *) data = swap_32(0); + len=4; + break; /* hub power ** */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + + status = in16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1)); + cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | + ((status & USBPORTSC_PEC) >> (3 - 1)) | + (rh.c_p_r[wIndex - 1] << (0 + 4)); + status = (status & USBPORTSC_CCS) | + ((status & USBPORTSC_PE) >> (2 - 1)) | + ((status & USBPORTSC_SUSP) >> (12 - 2)) | + ((status & USBPORTSC_PR) >> (9 - 4)) | + (1 << 8) | /* power on ** */ + ((status & USBPORTSC_LSDA) << (-8 + 9)); + + *(unsigned short *) data = swap_16(status); + *(unsigned short *) (data + 2) = swap_16(cstatus); + len=4; + break; + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): + len=0; + break; + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case (RH_C_HUB_OVER_CURRENT): + len=0; /* hub power over current ** */ + break; + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + usb_display_wValue(wValue,wIndex); + switch (wValue) { + case (RH_PORT_ENABLE): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) & ~USBPORTSC_PE; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_PORT_SUSPEND): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) & ~USBPORTSC_SUSP; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_PORT_POWER): + len=0; /* port power ** */ + break; + case (RH_C_PORT_CONNECTION): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_CSC; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_C_PORT_ENABLE): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_PEC; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_C_PORT_SUSPEND): +/*** WR_RH_PORTSTAT(RH_PS_PSSC); */ + len=0; + break; + case (RH_C_PORT_OVER_CURRENT): + len=0; + break; + case (RH_C_PORT_RESET): + rh.c_p_r[wIndex - 1] = 0; + len=0; + break; + } + break; + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + usb_display_wValue(wValue,wIndex); + switch (wValue) { + case (RH_PORT_SUSPEND): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_SUSP; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_PORT_RESET): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_PR; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + wait_ms(10); + status = (status & 0xfff5) & ~USBPORTSC_PR; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + udelay(10); + status = (status & 0xfff5) | USBPORTSC_PE; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + wait_ms(10); + status = (status & 0xfff5) | 0xa; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_PORT_POWER): + len=0; /* port power ** */ + break; + case (RH_PORT_ENABLE): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_PE; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + } + break; + + case RH_SET_ADDRESS: + rh.devnum = wValue; + len=0; + break; + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + i=sizeof(root_hub_config_des); + status=i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_dev_des, len); + break; + case (0x02): /* configuration descriptor */ + i=sizeof(root_hub_config_des); + status=i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_config_des, len); + break; + case (0x03): /*string descriptors */ + if(wValue==0x0300) { + i=sizeof(root_hub_str_index0); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_str_index0, len); + break; + } + if(wValue==0x0301) { + i=sizeof(root_hub_str_index1); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_str_index1, len); + break; + } + stat = USB_ST_STALLED; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + root_hub_hub_des[2] = 2; + i=sizeof(root_hub_hub_des); + status= i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_hub_des, len); + break; + case RH_GET_CONFIGURATION: + *(unsigned char *) data = 0x01; + len = 1; + break; + case RH_SET_CONFIGURATION: + len=0; + break; + default: + stat = USB_ST_STALLED; + } + USB_RH_PRINTF("Root-Hub stat %lx port1: %x port2: %x\n\n",stat, + in16r(usb_base_addr + USBPORTSC1), in16r(usb_base_addr + USBPORTSC2)); + dev->act_len=len; + dev->status=stat; + return stat; + +} + +/******************************************************************************** + * Some Debug Routines + */ + +#ifdef USB_RH_DEBUG + +static void usb_display_Req(unsigned short req) +{ + USB_RH_PRINTF("- Root-Hub Request: "); + switch (req) { + case RH_GET_STATUS: + USB_RH_PRINTF("Get Status "); + break; + case RH_GET_STATUS | RH_INTERFACE: + USB_RH_PRINTF("Get Status Interface "); + break; + case RH_GET_STATUS | RH_ENDPOINT: + USB_RH_PRINTF("Get Status Endpoint "); + break; + case RH_GET_STATUS | RH_CLASS: + USB_RH_PRINTF("Get Status Class"); + break; /* hub power ** */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Get Status Class Others"); + break; + case RH_CLEAR_FEATURE | RH_ENDPOINT: + USB_RH_PRINTF("Clear Feature Endpoint "); + break; + case RH_CLEAR_FEATURE | RH_CLASS: + USB_RH_PRINTF("Clear Feature Class "); + break; + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Clear Feature Other Class "); + break; + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Set Feature Other Class "); + break; + case RH_SET_ADDRESS: + USB_RH_PRINTF("Set Address "); + break; + case RH_GET_DESCRIPTOR: + USB_RH_PRINTF("Get Descriptor "); + break; + case RH_GET_DESCRIPTOR | RH_CLASS: + USB_RH_PRINTF("Get Descriptor Class "); + break; + case RH_GET_CONFIGURATION: + USB_RH_PRINTF("Get Configuration "); + break; + case RH_SET_CONFIGURATION: + USB_RH_PRINTF("Get Configuration "); + break; + default: + USB_RH_PRINTF("****UNKNOWN**** 0x%04X ",req); + } + USB_RH_PRINTF("\n"); + +} + +static void usb_display_wValue(unsigned short wValue,unsigned short wIndex) +{ + switch (wValue) { + case (RH_PORT_ENABLE): + USB_RH_PRINTF("Root-Hub: Enable Port %d\n",wIndex); + break; + case (RH_PORT_SUSPEND): + USB_RH_PRINTF("Root-Hub: Suspend Port %d\n",wIndex); + break; + case (RH_PORT_POWER): + USB_RH_PRINTF("Root-Hub: Port Power %d\n",wIndex); + break; + case (RH_C_PORT_CONNECTION): + USB_RH_PRINTF("Root-Hub: C Port Connection Port %d\n",wIndex); + break; + case (RH_C_PORT_ENABLE): + USB_RH_PRINTF("Root-Hub: C Port Enable Port %d\n",wIndex); + break; + case (RH_C_PORT_SUSPEND): + USB_RH_PRINTF("Root-Hub: C Port Suspend Port %d\n",wIndex); + break; + case (RH_C_PORT_OVER_CURRENT): + USB_RH_PRINTF("Root-Hub: C Port Over Current Port %d\n",wIndex); + break; + case (RH_C_PORT_RESET): + USB_RH_PRINTF("Root-Hub: C Port reset Port %d\n",wIndex); + break; + default: + USB_RH_PRINTF("Root-Hub: unknown %x %x\n",wValue,wIndex); + break; + } +} + +#endif + + +#ifdef USB_UHCI_DEBUG + +static int usb_display_td(uhci_td_t *td) +{ + unsigned long tmp; + int valid; + + printf("TD at %p:\n",td); + + tmp=swap_32(td->link); + printf("Link points to 0x%08lX, %s first, %s, %s\n",tmp&0xfffffff0, + ((tmp & 0x4)==0x4) ? "Depth" : "Breath", + ((tmp & 0x2)==0x2) ? "QH" : "TD", + ((tmp & 0x1)==0x1) ? "invalid" : "valid"); + valid=((tmp & 0x1)==0x0); + tmp=swap_32(td->status); + printf(" %s %ld Errors %s %s %s \n %s %s %s %s %s %s\n Len 0x%lX\n", + (((tmp>>29)&0x1)==0x1) ? "SPD Enable" : "SPD Disable", + ((tmp>>28)&0x3), + (((tmp>>26)&0x1)==0x1) ? "Low Speed" : "Full Speed", + (((tmp>>25)&0x1)==0x1) ? "ISO " : "", + (((tmp>>24)&0x1)==0x1) ? "IOC " : "", + (((tmp>>23)&0x1)==0x1) ? "Active " : "Inactive ", + (((tmp>>22)&0x1)==0x1) ? "Stalled" : "", + (((tmp>>21)&0x1)==0x1) ? "Data Buffer Error" : "", + (((tmp>>20)&0x1)==0x1) ? "Babble" : "", + (((tmp>>19)&0x1)==0x1) ? "NAK" : "", + (((tmp>>18)&0x1)==0x1) ? "Bitstuff Error" : "", + (tmp&0x7ff)); + tmp=swap_32(td->info); + printf(" MaxLen 0x%lX\n",((tmp>>21)&0x7FF)); + printf(" %s Endpoint 0x%lX Dev Addr 0x%lX PID 0x%lX\n",((tmp>>19)&0x1)==0x1 ? "TOGGLE" : "", + ((tmp>>15)&0xF),((tmp>>8)&0x7F),tmp&0xFF); + tmp=swap_32(td->buffer); + printf(" Buffer 0x%08lX\n",tmp); + printf(" DEV %08lX\n",td->dev_ptr); + return valid; +} + + +void usb_show_td(int max) +{ + int i; + if(max>0) { + for(i=0;i<max;i++) { + usb_display_td(&tmp_td[i]); + } + } + else { + i=0; + do { + printf("tmp_td[%d]\n",i); + }while(usb_display_td(&tmp_td[i++])); + } +} + + +#endif +#endif /* CONFIG_USB_UHCI */ + +/* EOF */ diff --git a/u-boot/board/mpl/common/usb_uhci.h b/u-boot/board/mpl/common/usb_uhci.h new file mode 100644 index 0000000..af80837 --- /dev/null +++ b/u-boot/board/mpl/common/usb_uhci.h @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + * Note: Part of this code has been derived from linux + * + */ +#ifndef _USB_UHCI_H_ +#define _USB_UHCI_H_ + + +/* Command register */ +#define USBCMD 0 +#define USBCMD_RS 0x0001 /* Run/Stop */ +#define USBCMD_HCRESET 0x0002 /* Host reset */ +#define USBCMD_GRESET 0x0004 /* Global reset */ +#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define USBCMD_FGR 0x0010 /* Force Global Resume */ +#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ +#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ +#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ + +/* Status register */ +#define USBSTS 2 +#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ +#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ +#define USBSTS_RD 0x0004 /* Resume Detect */ +#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ +#define USBSTS_HCH 0x0020 /* HC Halted */ + +/* Interrupt enable register */ +#define USBINTR 4 +#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ +#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ +#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ +#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ + +#define USBFRNUM 6 +#define USBFLBASEADD 8 +#define USBSOF 12 + +/* USB port status and control registers */ +#define USBPORTSC1 16 +#define USBPORTSC2 18 +#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ +#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ +#define USBPORTSC_PE 0x0004 /* Port Enable */ +#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ +#define USBPORTSC_LS 0x0030 /* Line Status */ +#define USBPORTSC_RD 0x0040 /* Resume Detect */ +#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ +#define USBPORTSC_PR 0x0200 /* Port Reset */ +#define USBPORTSC_SUSP 0x1000 /* Suspend */ + +/* Legacy support register */ +#define USBLEGSUP 0xc0 +#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ + +#define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */ +#define UHCI_PID 0xff /* PID MASK */ + +#define UHCI_PTR_BITS 0x000F +#define UHCI_PTR_TERM 0x0001 +#define UHCI_PTR_QH 0x0002 +#define UHCI_PTR_DEPTH 0x0004 + +/* for TD <status>: */ +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ +#define TD_CTRL_ACTLEN_MASK 0x7ff /* actual length, encoded as n - 1 */ + +#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) + +#define TD_TOKEN_TOGGLE 19 + +/* ------------------------------------------------------------------------------------ + Virtual Root HUB + ------------------------------------------------------------------------------------ */ +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +/* Our Vendor Specific feature */ +#define RH_REMOVE_EP 0x00 + + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + + +/* Transfer descriptor structure */ +typedef struct { + unsigned long link; /* next td/qh (LE)*/ + unsigned long status; /* status of the td */ + unsigned long info; /* Max Lenght / Endpoint / device address and PID */ + unsigned long buffer; /* pointer to data buffer (LE) */ + unsigned long dev_ptr; /* pointer to the assigned device (BE) */ + unsigned long res[3]; /* reserved (TDs must be 8Byte aligned) */ +} uhci_td_t, *puhci_td_t; + +/* Queue Header structure */ +typedef struct { + unsigned long head; /* Next QH (LE)*/ + unsigned long element; /* Queue element pointer (LE) */ + unsigned long res[5]; /* reserved */ + unsigned long dev_ptr; /* if 0 no tds have been assigned to this qh */ +} uhci_qh_t, *puhci_qh_t; + +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + int numports; /* number of ports */ + int c_p_r[8]; /* C_PORT_RESET */ +}; + + +#endif /* _USB_UHCI_H_ */ diff --git a/u-boot/board/mpl/mip405/Makefile b/u-boot/board/mpl/mip405/Makefile new file mode 100644 index 0000000..042cd83 --- /dev/null +++ b/u-boot/board/mpl/mip405/Makefile @@ -0,0 +1,56 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)../common) +endif + +LIB = $(obj)lib$(BOARD).o + +COBJS = $(BOARD).o ../common/flash.o cmd_mip405.o ../common/pci.o \ + ../common/usb_uhci.o ../common/common_util.o + +SOBJS = init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(OBJS) $(SOBJS) + $(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/board/mpl/mip405/cmd_mip405.c b/u-boot/board/mpl/mip405/cmd_mip405.c new file mode 100644 index 0000000..f7cc37b --- /dev/null +++ b/u-boot/board/mpl/mip405/cmd_mip405.c @@ -0,0 +1,65 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 MIP405 + */ + +#include <common.h> +#include <command.h> +#include "mip405.h" +#include "../common/common_util.h" + + +extern void print_mip405_info(void); +extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + + +/* ------------------------------------------------------------------------- */ + +int do_mip405(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + + ulong led_on; + + if (strcmp(argv[1], "info") == 0) + { + print_mip405_info(); + return 0; + } + if (strcmp(argv[1], "led") == 0) + { + led_on = (ulong)simple_strtoul(argv[2], NULL, 10); + user_led0(led_on); + return 0; + } + return (do_mplcommon(cmdtp, flag, argc, argv)); +} +U_BOOT_CMD( + mip405, 8, 1, do_mip405, + "MIP405 specific Cmds", + "flash mem [SrcAddr] - updates U-Boot with image in memory\n" + "mip405 flash mps - updates U-Boot with image from MPS\n" + "mip405 info - displays board information\n" + "mip405 led <on> - switches LED on (on=1) or off (on=0)" +); + +/* ------------------------------------------------------------------------- */ diff --git a/u-boot/board/mpl/mip405/init.S b/u-boot/board/mpl/mip405/init.S new file mode 100644 index 0000000..39a1d68 --- /dev/null +++ b/u-boot/board/mpl/mip405/init.S @@ -0,0 +1,221 @@ +/*------------------------------------------------------------------------------+ + * This source code is dual-licensed. You may use it under the terms of + * the GNU General Public License version 2, or under the license below. + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + *-------------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Function: ext_bus_cntlr_init + * Description: Initializes the External Bus Controller for the external + * peripherals. IMPORTANT: For pass1 this code must run from + * cache since you can not reliably change a peripheral banks + * timing register (pbxap) while running code from that bank. + * For ex., since we are running from ROM on bank 0, we can NOT + * execute the code that modifies bank 0 timings from ROM, so + * we run it from cache. + * Bank 0 - Flash or Multi Purpose Socket + * Bank 1 - Multi Purpose Socket or Flash (set in C-Code) + * Bank 2 - UART 1 (set in C-Code) + * Bank 3 - UART 2 (set in C-Code) + * Bank 4 - not used + * Bank 5 - not used + * Bank 6 - not used + * Bank 7 - PLD Register + *-----------------------------------------------------------------------------*/ +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <configs/MIP405.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> +#include <asm/ppc4xx.h> +#include "mip405.h" + + + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: + mflr r4 /* save link register */ + mfdcr r3,CPC0_PSR /* get strapping reg */ + andi. r0, r3, PSR_ROM_LOC /* mask out irrelevant bits */ + bnelr /* jump back if PCI boot */ + + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + mtlr r4 /* restore link register */ + addi r4,0,14 /* set ctr to 14; used to prefetch */ + mtctr r4 /* 14 cache lines to fit this function */ + /* in cache (gives us 8x14=112 instrctns) */ +..ebcloop: + icbt r0,r3 /* prefetch cache line for addr in r3 */ + addi r3,r3,32 /* move to next cache line */ + bdnz ..ebcloop /* continue for 14 cache lines */ + + /*------------------------------------------------------------------- + * Delay to ensure all accesses to ROM are complete before changing + * bank 0 timings. + *------------------------------------------------------------------- */ + addis r3,0,0x0 + ori r3,r3,0xA000 + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + + /*----------------------------------------------------------------------- + * decide boot up mode + *----------------------------------------------------------------------- */ + addi r4,0,PB0CR + mtdcr EBC0_CFGADDR,r4 + mfdcr r4,EBC0_CFGDATA + + andi. r0, r4, 0x2000 /* mask out irrelevant bits */ + beq 0f /* jump if 8 bit bus width */ + + /* setup 16 bit things + *----------------------------------------------------------------------- + * Memory Bank 0 (16 Bit Flash) initialization + *---------------------------------------------------------------------- */ + + addi r4,0,PB1AP + mtdcr EBC0_CFGADDR,r4 + addis r4,0,(FLASH_AP_B)@h + ori r4,r4,(FLASH_AP_B)@l + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB0CR + mtdcr EBC0_CFGADDR,r4 + /* BS=0x010(4MB),BU=0x3(R/W), */ + addis r4,0,(FLASH_CR_B)@h + ori r4,r4,(FLASH_CR_B)@l + mtdcr EBC0_CFGDATA,r4 + b 1f + +0: + + /* 8Bit boot mode: */ + /*----------------------------------------------------------------------- + * Memory Bank 0 Multi Purpose Socket initialization + *----------------------------------------------------------------------- */ + /* 0x7F8FFE80 slowest boot */ + addi r4,0,PB1AP + mtdcr EBC0_CFGADDR,r4 + addis r4,0,(MPS_AP_B)@h + ori r4,r4,(MPS_AP_B)@l + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB0CR + mtdcr EBC0_CFGADDR,r4 + /* BS=0x010(4MB),BU=0x3(R/W), */ + addis r4,0,(MPS_CR_B)@h + ori r4,r4,(MPS_CR_B)@l + + mtdcr EBC0_CFGDATA,r4 + + +1: + /*----------------------------------------------------------------------- + * Memory Bank 2-3-4-5-6 (not used) initialization + *-----------------------------------------------------------------------*/ + addi r4,0,PB1CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB2CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB3CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB4CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB5CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB6CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB7CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + nop /* pass2 DCR errata #8 */ + blr + +#if defined(CONFIG_BOOT_PCI) + .section .bootpg,"ax" + .globl _start_pci +/******************************************* + */ + +_start_pci: + /* first handle errata #68 / PCI_18 */ + iccci r0, r0 /* invalidate I-cache */ + lis r31, 0 + mticcr r31 /* ICCR = 0 (all uncachable) */ + isync + + mfccr0 r28 /* set CCR0[24] = 1 */ + ori r28, r28, 0x0080 + mtccr0 r28 + + /* setup PMM0MA (0xEF400004) and PMM0PCIHA (0xEF40000C) */ + lis r28, 0xEF40 + addi r28, r28, 0x0004 + stw r31, 0x0C(r28) /* clear PMM0PCIHA */ + lis r29, 0xFFF8 /* open 512 kByte */ + addi r29, r29, 0x0001/* and enable this region */ + stwbrx r29, r0, r28 /* write PMM0MA */ + + lis r28, 0xEEC0 /* address of PCIC0_CFGADDR */ + addi r29, r28, 4 /* add 4 to r29 -> PCIC0_CFGDATA */ + + lis r31, 0x8000 /* set en bit bus 0 */ + ori r31, r31, 0x304C/* device 6 func 0 reg 4C (XBCS register) */ + stwbrx r31, r0, r28 /* write it */ + + lwbrx r31, r0, r29 /* load XBCS register */ + oris r31, r31, 0x02C4/* clear BIOSCS WPE, set lower, extended and 1M extended BIOS enable */ + stwbrx r31, r0, r29 /* write back XBCS register */ + + nop + nop + b _start /* normal start */ +#endif diff --git a/u-boot/board/mpl/mip405/mip405.c b/u-boot/board/mpl/mip405/mip405.c new file mode 100644 index 0000000..e93d994 --- /dev/null +++ b/u-boot/board/mpl/mip405/mip405.c @@ -0,0 +1,805 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * + * TODO: clean-up + */ + +/* + * How do I program the SDRAM Timing Register (SDRAM0_TR) for a specific SDRAM or DIMM? + * + * As an example, consider a case where PC133 memory with CAS Latency equal to 2 is being + * used with a 200MHz 405GP. For a typical 128Mb, PC133 SDRAM, the relevant minimum + * parameters from the datasheet are: + * Tclk = 7.5ns (CL = 2) + * Trp = 15ns + * Trc = 60ns + * Trcd = 15ns + * Trfc = 66ns + * + * If we are operating the 405GP with the MemClk output frequency set to 100 MHZ, the clock + * period is 10ns and the parameters needed for the Timing Register are: + * CASL = CL = 2 clock cycles + * PTA = Trp = 15ns / 10ns = 2 clock cycles + * CTP = Trc - Trcd - Trp = (60ns - 15ns - 15ns) / 10ns= 3 clock cycles + * LDF = 2 clock cycles (but can be extended to meet board-level timing) + * RFTA = Trfc = 66ns / 10ns= 7 clock cycles + * RCD = Trcd = 15ns / 10ns= 2 clock cycles + * + * The actual bit settings in the register would be: + * + * CASL = 0b01 + * PTA = 0b01 + * CTP = 0b10 + * LDF = 0b01 + * RFTA = 0b011 + * RCD = 0b01 + * + * If Trfc is not specified in the datasheet for PC100 or PC133 memory, set RFTA = Trc + * instead. Figure 24 in the PC SDRAM Specification Rev. 1.7 shows refresh to active delay + * defined as Trc rather than Trfc. + * When using DIMM modules, most but not all of the required timing parameters can be read + * from the Serial Presence Detect (SPD) EEPROM on the module. Specifically, Trc and Trfc + * are not available from the EEPROM + */ + +#include <common.h> +#include "mip405.h" +#include <asm/processor.h> +#include <asm/ppc4xx.h> +#include <asm/ppc4xx-i2c.h> +#include <miiphy.h> +#include "../common/common_util.h" +#include <stdio_dev.h> +#include <i2c.h> +#include <rtc.h> + +DECLARE_GLOBAL_DATA_PTR; + +#undef SDRAM_DEBUG +#define ENABLE_ECC /* for ecc boards */ +#define FALSE 0 +#define TRUE 1 + +/* stdlib.h causes some compatibility problems; should fixe these! -- wd */ +#ifndef __ldiv_t_defined +typedef struct { + long int quot; /* Quotient */ + long int rem; /* Remainder */ +} ldiv_t; +extern ldiv_t ldiv (long int __numer, long int __denom); +# define __ldiv_t_defined 1 +#endif + + +#define PLD_PART_REG PER_PLD_ADDR + 0 +#define PLD_VERS_REG PER_PLD_ADDR + 1 +#define PLD_BOARD_CFG_REG PER_PLD_ADDR + 2 +#define PLD_IRQ_REG PER_PLD_ADDR + 3 +#define PLD_COM_MODE_REG PER_PLD_ADDR + 4 +#define PLD_EXT_CONF_REG PER_PLD_ADDR + 5 + +#define MEGA_BYTE (1024*1024) + +typedef struct { + unsigned char boardtype; /* Board revision and Population Options */ + unsigned char cal; /* cas Latency (will be programmend as cal-1) */ + unsigned char trp; /* datain27 in clocks */ + unsigned char trcd; /* datain29 in clocks */ + unsigned char tras; /* datain30 in clocks */ + unsigned char tctp; /* tras - trcd in clocks */ + unsigned char am; /* Address Mod (will be programmed as am-1) */ + unsigned char sz; /* log binary => Size = (4MByte<<sz) 5 = 128, 4 = 64, 3 = 32, 2 = 16, 1=8 */ + unsigned char ecc; /* if true, ecc is enabled */ +} sdram_t; +#if defined(CONFIG_MIP405T) +const sdram_t sdram_table[] = { + { 0x0F, /* MIP405T Rev A, 64MByte -1 Board */ + 3, /* Case Latenty = 3 */ + 3, /* trp 20ns / 7.5 ns datain[27] */ + 3, /* trcd 20ns /7.5 ns (datain[29]) */ + 6, /* tras 44ns /7.5 ns (datain[30]) */ + 4, /* tcpt 44 - 20ns = 24ns */ + 2, /* Address Mode = 2 (12x9x4) */ + 3, /* size value (32MByte) */ + 0}, /* ECC disabled */ + { 0xff, /* terminator */ + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff } +}; +#else +const sdram_t sdram_table[] = { + { 0x0f, /* Rev A, 128MByte -1 Board */ + 3, /* Case Latenty = 3 */ + 3, /* trp 20ns / 7.5 ns datain[27] */ + 3, /* trcd 20ns /7.5 ns (datain[29]) */ + 6, /* tras 44ns /7.5 ns (datain[30]) */ + 4, /* tcpt 44 - 20ns = 24ns */ + 3, /* Address Mode = 3 */ + 5, /* size value */ + 1}, /* ECC enabled */ + { 0x07, /* Rev A, 64MByte -2 Board */ + 3, /* Case Latenty = 3 */ + 3, /* trp 20ns / 7.5 ns datain[27] */ + 3, /* trcd 20ns /7.5 ns (datain[29]) */ + 6, /* tras 44ns /7.5 ns (datain[30]) */ + 4, /* tcpt 44 - 20ns = 24ns */ + 2, /* Address Mode = 2 */ + 4, /* size value */ + 1}, /* ECC enabled */ + { 0x03, /* Rev A, 128MByte -4 Board */ + 3, /* Case Latenty = 3 */ + 3, /* trp 20ns / 7.5 ns datain[27] */ + 3, /* trcd 20ns /7.5 ns (datain[29]) */ + 6, /* tras 44ns /7.5 ns (datain[30]) */ + 4, /* tcpt 44 - 20ns = 24ns */ + 3, /* Address Mode = 3 */ + 5, /* size value */ + 1}, /* ECC enabled */ + { 0x1f, /* Rev B, 128MByte -3 Board */ + 3, /* Case Latenty = 3 */ + 3, /* trp 20ns / 7.5 ns datain[27] */ + 3, /* trcd 20ns /7.5 ns (datain[29]) */ + 6, /* tras 44ns /7.5 ns (datain[30]) */ + 4, /* tcpt 44 - 20ns = 24ns */ + 3, /* Address Mode = 3 */ + 5, /* size value */ + 1}, /* ECC enabled */ + { 0x2f, /* Rev C, 128MByte -3 Board */ + 3, /* Case Latenty = 3 */ + 3, /* trp 20ns / 7.5 ns datain[27] */ + 3, /* trcd 20ns /7.5 ns (datain[29]) */ + 6, /* tras 44ns /7.5 ns (datain[30]) */ + 4, /* tcpt 44 - 20ns = 24ns */ + 3, /* Address Mode = 3 */ + 5, /* size value */ + 1}, /* ECC enabled */ + { 0xff, /* terminator */ + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff } +}; +#endif /*CONFIG_MIP405T */ +void SDRAM_err (const char *s) +{ +#ifndef SDRAM_DEBUG + (void) get_clocks (); + gd->baudrate = 9600; + serial_init (); +#endif + serial_puts ("\n"); + serial_puts (s); + serial_puts ("\n enable SDRAM_DEBUG for more info\n"); + for (;;); +} + + +unsigned char get_board_revcfg (void) +{ + out8 (PER_BOARD_ADDR, 0); + return (in8 (PER_BOARD_ADDR)); +} + + +#ifdef SDRAM_DEBUG + +void write_hex (unsigned char i) +{ + char cc; + + cc = i >> 4; + cc &= 0xf; + if (cc > 9) + serial_putc (cc + 55); + else + serial_putc (cc + 48); + cc = i & 0xf; + if (cc > 9) + serial_putc (cc + 55); + else + serial_putc (cc + 48); +} + +void write_4hex (unsigned long val) +{ + write_hex ((unsigned char) (val >> 24)); + write_hex ((unsigned char) (val >> 16)); + write_hex ((unsigned char) (val >> 8)); + write_hex ((unsigned char) val); +} + +#endif + + +int init_sdram (void) +{ + unsigned long tmp, baseaddr; + unsigned short i; + unsigned char trp_clocks, + trcd_clocks, + tras_clocks, + trc_clocks, + tctp_clocks; + unsigned char cal_val; + unsigned char bc; + unsigned long sdram_tim, sdram_bank; + + /*i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);*/ + (void) get_clocks (); + gd->baudrate = 9600; + serial_init (); + /* set up the pld */ + mtdcr (EBC0_CFGADDR, PB7AP); + mtdcr (EBC0_CFGDATA, PLD_AP); + mtdcr (EBC0_CFGADDR, PB7CR); + mtdcr (EBC0_CFGDATA, PLD_CR); + /* THIS IS OBSOLETE */ + /* set up the board rev reg*/ + mtdcr (EBC0_CFGADDR, PB5AP); + mtdcr (EBC0_CFGDATA, BOARD_AP); + mtdcr (EBC0_CFGADDR, PB5CR); + mtdcr (EBC0_CFGDATA, BOARD_CR); +#ifdef SDRAM_DEBUG + /* get all informations from PLD */ + serial_puts ("\nPLD Part 0x"); + bc = in8 (PLD_PART_REG); + write_hex (bc); + serial_puts ("\nPLD Vers 0x"); + bc = in8 (PLD_VERS_REG); + write_hex (bc); + serial_puts ("\nBoard Rev 0x"); + bc = in8 (PLD_BOARD_CFG_REG); + write_hex (bc); + serial_puts ("\n"); +#endif + /* check board */ + bc = in8 (PLD_PART_REG); +#if defined(CONFIG_MIP405T) + if((bc & 0x80)==0) + SDRAM_err ("U-Boot configured for a MIP405T not for a MIP405!!!\n"); +#else + if((bc & 0x80)==0x80) + SDRAM_err ("U-Boot configured for a MIP405 not for a MIP405T!!!\n"); +#endif + /* set-up the chipselect machine */ + mtdcr (EBC0_CFGADDR, PB0CR); /* get cs0 config reg */ + tmp = mfdcr (EBC0_CFGDATA); + if ((tmp & 0x00002000) == 0) { + /* MPS Boot, set up the flash */ + mtdcr (EBC0_CFGADDR, PB1AP); + mtdcr (EBC0_CFGDATA, FLASH_AP); + mtdcr (EBC0_CFGADDR, PB1CR); + mtdcr (EBC0_CFGDATA, FLASH_CR); + } else { + /* Flash boot, set up the MPS */ + mtdcr (EBC0_CFGADDR, PB1AP); + mtdcr (EBC0_CFGDATA, MPS_AP); + mtdcr (EBC0_CFGADDR, PB1CR); + mtdcr (EBC0_CFGDATA, MPS_CR); + } + /* set up UART0 (CS2) and UART1 (CS3) */ + mtdcr (EBC0_CFGADDR, PB2AP); + mtdcr (EBC0_CFGDATA, UART0_AP); + mtdcr (EBC0_CFGADDR, PB2CR); + mtdcr (EBC0_CFGDATA, UART0_CR); + mtdcr (EBC0_CFGADDR, PB3AP); + mtdcr (EBC0_CFGDATA, UART1_AP); + mtdcr (EBC0_CFGADDR, PB3CR); + mtdcr (EBC0_CFGDATA, UART1_CR); + bc = in8 (PLD_BOARD_CFG_REG); +#ifdef SDRAM_DEBUG + serial_puts ("\nstart SDRAM Setup\n"); + serial_puts ("\nBoard Rev: "); + write_hex (bc); + serial_puts ("\n"); +#endif + i = 0; + baseaddr = CONFIG_SYS_SDRAM_BASE; + while (sdram_table[i].sz != 0xff) { + if (sdram_table[i].boardtype == bc) + break; + i++; + } + if (sdram_table[i].boardtype != bc) + SDRAM_err ("No SDRAM table found for this board!!!\n"); +#ifdef SDRAM_DEBUG + serial_puts (" found table "); + write_hex (i); + serial_puts (" \n"); +#endif + /* since the ECC initialisation needs some time, + * we show that we're alive + */ + if (sdram_table[i].ecc) + serial_puts ("\nInitializing SDRAM, Please stand by"); + cal_val = sdram_table[i].cal - 1; /* Cas Latency */ + trp_clocks = sdram_table[i].trp; /* 20ns / 7.5 ns datain[27] */ + trcd_clocks = sdram_table[i].trcd; /* 20ns /7.5 ns (datain[29]) */ + tras_clocks = sdram_table[i].tras; /* 44ns /7.5 ns (datain[30]) */ + /* ctp = ((trp + tras) - trp - trcd) => tras - trcd */ + tctp_clocks = sdram_table[i].tctp; /* 44 - 20ns = 24ns */ + /* trc_clocks is sum of trp_clocks + tras_clocks */ + trc_clocks = trp_clocks + tras_clocks; + /* get SDRAM timing register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_TR); + sdram_tim = mfdcr (SDRAM0_CFGDATA) & ~0x018FC01F; + /* insert CASL value */ + sdram_tim |= ((unsigned long) (cal_val)) << 23; + /* insert PTA value */ + sdram_tim |= ((unsigned long) (trp_clocks - 1)) << 18; + /* insert CTP value */ + sdram_tim |= + ((unsigned long) (trc_clocks - trp_clocks - + trcd_clocks)) << 16; + /* insert LDF (always 01) */ + sdram_tim |= ((unsigned long) 0x01) << 14; + /* insert RFTA value */ + sdram_tim |= ((unsigned long) (trc_clocks - 4)) << 2; + /* insert RCD value */ + sdram_tim |= ((unsigned long) (trcd_clocks - 1)) << 0; + + tmp = ((unsigned long) (sdram_table[i].am - 1) << 13); /* AM = 3 */ + /* insert SZ value; */ + tmp |= ((unsigned long) sdram_table[i].sz << 17); + /* get SDRAM bank 0 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); + sdram_bank = mfdcr (SDRAM0_CFGDATA) & ~0xFFCEE001; + sdram_bank |= (baseaddr | tmp | 0x01); + +#ifdef SDRAM_DEBUG + serial_puts ("sdtr: "); + write_4hex (sdram_tim); + serial_puts ("\n"); +#endif + + /* write SDRAM timing register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_TR); + mtdcr (SDRAM0_CFGDATA, sdram_tim); + +#ifdef SDRAM_DEBUG + serial_puts ("mb0cf: "); + write_4hex (sdram_bank); + serial_puts ("\n"); +#endif + + /* write SDRAM bank 0 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); + mtdcr (SDRAM0_CFGDATA, sdram_bank); + + if (get_bus_freq (tmp) > 110000000) { /* > 110MHz */ + /* get SDRAM refresh interval register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_RTR); + tmp = mfdcr (SDRAM0_CFGDATA) & ~0x3FF80000; + tmp |= 0x07F00000; + } else { + /* get SDRAM refresh interval register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_RTR); + tmp = mfdcr (SDRAM0_CFGDATA) & ~0x3FF80000; + tmp |= 0x05F00000; + } + /* write SDRAM refresh interval register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_RTR); + mtdcr (SDRAM0_CFGDATA, tmp); + /* enable ECC if used */ +#if defined(ENABLE_ECC) && !defined(CONFIG_BOOT_PCI) + if (sdram_table[i].ecc) { + /* disable checking for all banks */ + unsigned long *p; +#ifdef SDRAM_DEBUG + serial_puts ("disable ECC.. "); +#endif + mtdcr (SDRAM0_CFGADDR, SDRAM0_ECCCFG); + tmp = mfdcr (SDRAM0_CFGDATA); + tmp &= 0xff0fffff; /* disable all banks */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_ECCCFG); + /* set up SDRAM Controller with ECC enabled */ +#ifdef SDRAM_DEBUG + serial_puts ("setup SDRAM Controller.. "); +#endif + mtdcr (SDRAM0_CFGDATA, tmp); + mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); + tmp = (mfdcr (SDRAM0_CFGDATA) & ~0xFFE00000) | 0x90800000; + mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); + mtdcr (SDRAM0_CFGDATA, tmp); + udelay (600); +#ifdef SDRAM_DEBUG + serial_puts ("fill the memory..\n"); +#endif + serial_puts ("."); + /* now, fill all the memory */ + tmp = ((4 * MEGA_BYTE) << sdram_table[i].sz); + p = (unsigned long) 0; + while ((unsigned long) p < tmp) { + *p++ = 0L; + if (!((unsigned long) p % 0x00800000)) /* every 8MByte */ + serial_puts ("."); + } + /* enable bank 0 */ + serial_puts ("."); +#ifdef SDRAM_DEBUG + serial_puts ("enable ECC\n"); +#endif + udelay (400); + mtdcr (SDRAM0_CFGADDR, SDRAM0_ECCCFG); + tmp = mfdcr (SDRAM0_CFGDATA); + tmp |= 0x00800000; /* enable bank 0 */ + mtdcr (SDRAM0_CFGDATA, tmp); + udelay (400); + } else +#endif + { + /* enable SDRAM controller with no ECC, 32-bit SDRAM width, 16 byte burst */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); + tmp = (mfdcr (SDRAM0_CFGDATA) & ~0xFFE00000) | 0x80C00000; + mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); + mtdcr (SDRAM0_CFGDATA, tmp); + udelay (400); + } + serial_puts ("\n"); + return (0); +} + +int board_early_init_f (void) +{ + init_sdram (); + + /*-------------------------------------------------------------------------+ + | Interrupt controller setup for the PIP405 board. + | Note: IRQ 0-15 405GP internally generated; active high; level sensitive + | IRQ 16 405GP internally generated; active low; level sensitive + | IRQ 17-24 RESERVED + | IRQ 25 (EXT IRQ 0) SouthBridge; active low; level sensitive + | IRQ 26 (EXT IRQ 1) NMI: active low; level sensitive + | IRQ 27 (EXT IRQ 2) SMI: active Low; level sensitive + | IRQ 28 (EXT IRQ 3) PCI SLOT 3; active low; level sensitive + | IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive + | IRQ 30 (EXT IRQ 5) PCI SLOT 1; active low; level sensitive + | IRQ 31 (EXT IRQ 6) PCI SLOT 0; active low; level sensitive + | Note for MIP405 board: + | An interrupt taken for the SouthBridge (IRQ 25) indicates that + | the Interrupt Controller in the South Bridge has caused the + | interrupt. The IC must be read to determine which device + | caused the interrupt. + | + +-------------------------------------------------------------------------*/ + mtdcr (UIC0SR, 0xFFFFFFFF); /* clear all ints */ + mtdcr (UIC0ER, 0x00000000); /* disable all ints */ + mtdcr (UIC0CR, 0x00000000); /* set all to be non-critical (for now) */ + mtdcr (UIC0PR, 0xFFFFFF80); /* set int polarities */ + mtdcr (UIC0TR, 0x10000000); /* set int trigger levels */ + mtdcr (UIC0VCR, 0x00000001); /* set vect base=0,INT0 highest priority */ + mtdcr (UIC0SR, 0xFFFFFFFF); /* clear all ints */ + return 0; +} + + +/* + * Get some PLD Registers + */ + +unsigned short get_pld_parvers (void) +{ + unsigned short result; + unsigned char rc; + + rc = in8 (PLD_PART_REG); + result = (unsigned short) rc << 8; + rc = in8 (PLD_VERS_REG); + result |= rc; + return result; +} + + +void user_led0 (unsigned char on) +{ + if (on) + out8 (PLD_COM_MODE_REG, (in8 (PLD_COM_MODE_REG) | 0x4)); + else + out8 (PLD_COM_MODE_REG, (in8 (PLD_COM_MODE_REG) & 0xfb)); +} + + +void ide_set_reset (int idereset) +{ + /* if reset = 1 IDE reset will be asserted */ + if (idereset) + out8 (PLD_COM_MODE_REG, (in8 (PLD_COM_MODE_REG) | 0x1)); + else { + udelay (10000); + out8 (PLD_COM_MODE_REG, (in8 (PLD_COM_MODE_REG) & 0xfe)); + } +} + + +/* ------------------------------------------------------------------------- */ + +void get_pcbrev_var(unsigned char *pcbrev, unsigned char *var) +{ +#if !defined(CONFIG_MIP405T) + unsigned char bc,rc,tmp; + int i; + + bc = in8 (PLD_BOARD_CFG_REG); + tmp = ~bc; + tmp &= 0xf; + rc = 0; + for (i = 0; i < 4; i++) { + rc <<= 1; + rc += (tmp & 0x1); + tmp >>= 1; + } + rc++; + if(( (((bc>>4) & 0xf)==0x2) /* Rev C PCB or */ + || (((bc>>4) & 0xf)==0x1)) /* Rev B PCB with */ + && (rc==0x1)) /* Population Option 1 is a -3 */ + rc=3; + *pcbrev=(bc >> 4) & 0xf; + *var=rc; +#else + unsigned char bc; + bc = in8 (PLD_BOARD_CFG_REG); + *pcbrev=(bc >> 4) & 0xf; + *var=16-(bc & 0xf); +#endif +} + +/* + * Check Board Identity: + */ +/* serial String: "MIP405_1000" OR "MIP405T_1000" */ +#if !defined(CONFIG_MIP405T) +#define BOARD_NAME "MIP405" +#else +#define BOARD_NAME "MIP405T" +#endif + +int checkboard (void) +{ + char s[50]; + unsigned char bc, var; + int i; + backup_t *b = (backup_t *) s; + + puts ("Board: "); + get_pcbrev_var(&bc,&var); + i = getenv_f("serial#", (char *)s, 32); + if ((i == 0) || strncmp ((char *)s, BOARD_NAME,sizeof(BOARD_NAME))) { + get_backup_values (b); + if (strncmp (b->signature, "MPL\0", 4) != 0) { + puts ("### No HW ID - assuming " BOARD_NAME); + printf ("-%d Rev %c", var, 'A' + bc); + } else { + b->serial_name[sizeof(BOARD_NAME)-1] = 0; + printf ("%s-%d Rev %c SN: %s", b->serial_name, var, + 'A' + bc, &b->serial_name[sizeof(BOARD_NAME)]); + } + } else { + s[sizeof(BOARD_NAME)-1] = 0; + printf ("%s-%d Rev %c SN: %s", s, var,'A' + bc, + &s[sizeof(BOARD_NAME)]); + } + bc = in8 (PLD_EXT_CONF_REG); + printf (" Boot Config: 0x%x\n", bc); + return (0); +} + + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +/* + initdram(int board_type) reads EEPROM via I2c. EEPROM contains all of + the necessary info for SDRAM controller configuration +*/ +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +static int test_dram (unsigned long ramsize); + +phys_size_t initdram (int board_type) +{ + + unsigned long bank_reg[4], tmp, bank_size; + int i, ds; + unsigned long TotalSize; + + ds = 0; + /* since the DRAM controller is allready set up, calculate the size with the + bank registers */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); + bank_reg[0] = mfdcr (SDRAM0_CFGDATA); + mtdcr (SDRAM0_CFGADDR, SDRAM0_B1CR); + bank_reg[1] = mfdcr (SDRAM0_CFGDATA); + mtdcr (SDRAM0_CFGADDR, SDRAM0_B2CR); + bank_reg[2] = mfdcr (SDRAM0_CFGDATA); + mtdcr (SDRAM0_CFGADDR, SDRAM0_B3CR); + bank_reg[3] = mfdcr (SDRAM0_CFGDATA); + TotalSize = 0; + for (i = 0; i < 4; i++) { + if ((bank_reg[i] & 0x1) == 0x1) { + tmp = (bank_reg[i] >> 17) & 0x7; + bank_size = 4 << tmp; + TotalSize += bank_size; + } else + ds = 1; + } + mtdcr (SDRAM0_CFGADDR, SDRAM0_ECCCFG); + tmp = mfdcr (SDRAM0_CFGDATA); + + if (!tmp) + printf ("No "); + printf ("ECC "); + + test_dram (TotalSize * MEGA_BYTE); + return (TotalSize * MEGA_BYTE); +} + +/* ------------------------------------------------------------------------- */ + + +static int test_dram (unsigned long ramsize) +{ +#ifdef SDRAM_DEBUG + mem_test (0L, ramsize, 1); +#endif + /* not yet implemented */ + return (1); +} + +/* used to check if the time in RTC is valid */ +static unsigned long start; +static struct rtc_time tm; +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +int misc_init_r (void) +{ + /* adjust flash start and size as well as the offset */ + gd->bd->bi_flashstart=0-flash_info[0].size; + gd->bd->bi_flashsize=flash_info[0].size-CONFIG_SYS_MONITOR_LEN; + gd->bd->bi_flashoffset=0; + + /* check, if RTC is running */ + rtc_get (&tm); + start=get_timer(0); + /* if MIP405 has booted from PCI, reset CCR0[24] as described in errata PCI_18 */ + if (mfdcr(CPC0_PSR) & PSR_ROM_LOC) + mtspr(SPRN_CCR0, (mfspr(SPRN_CCR0) & ~0x80)); + + return (0); +} + + +void print_mip405_rev (void) +{ + unsigned char part, vers, pcbrev, var; + + get_pcbrev_var(&pcbrev,&var); + part = in8 (PLD_PART_REG); + vers = in8 (PLD_VERS_REG); + printf ("Rev: " BOARD_NAME "-%d Rev %c PLD %d Vers %d\n", + var, pcbrev + 'A', part & 0x7F, vers); +} + + +extern int mk_date (char *, struct rtc_time *); + +int last_stage_init (void) +{ + unsigned long stop; + struct rtc_time newtm; + char *s; + + /* write correct LED configuration */ + if (miiphy_write("ppc_4xx_eth0", 0x1, 0x14, 0x2402) != 0) { + printf ("Error writing to the PHY\n"); + } + /* since LED/CFG2 is not connected on the -2, + * write to correct capability information */ + if (miiphy_write("ppc_4xx_eth0", 0x1, 0x4, 0x01E1) != 0) { + printf ("Error writing to the PHY\n"); + } + print_mip405_rev (); + stdio_print_current_devices (); + check_env (); + /* check if RTC time is valid */ + stop=get_timer(start); + while(stop<1200) { /* we wait 1.2 sec to check if the RTC is running */ + udelay(1000); + stop=get_timer(start); + } + rtc_get (&newtm); + if(tm.tm_sec==newtm.tm_sec) { + s=getenv("defaultdate"); + if(!s) + mk_date ("010112001970", &newtm); + else + if(mk_date (s, &newtm)!=0) { + printf("RTC: Bad date format in defaultdate\n"); + return 0; + } + rtc_reset (); + rtc_set(&newtm); + } + return 0; +} + +/*************************************************************************** + * some helping routines + */ + +int overwrite_console (void) +{ + return ((in8 (PLD_EXT_CONF_REG) & 0x1)==0); /* return TRUE if console should be overwritten */ +} + + +/************************************************************************ +* Print MIP405 Info +************************************************************************/ +void print_mip405_info (void) +{ + unsigned char part, vers, cfg, irq_reg, com_mode, ext; + + part = in8 (PLD_PART_REG); + vers = in8 (PLD_VERS_REG); + cfg = in8 (PLD_BOARD_CFG_REG); + irq_reg = in8 (PLD_IRQ_REG); + com_mode = in8 (PLD_COM_MODE_REG); + ext = in8 (PLD_EXT_CONF_REG); + + printf ("PLD Part %d version %d\n", part & 0x7F, vers); + printf ("Board Revision %c\n", ((cfg >> 4) & 0xf) + 'A'); + printf ("Population Options %d %d %d %d\n", (cfg) & 0x1, + (cfg >> 1) & 0x1, (cfg >> 2) & 0x1, (cfg >> 3) & 0x1); + printf ("User LED %s\n", (com_mode & 0x4) ? "on" : "off"); + printf ("UART Clocks %d\n", (com_mode >> 4) & 0x3); +#if !defined(CONFIG_MIP405T) + printf ("User Config Switch %d %d %d %d %d %d %d %d\n", + (ext) & 0x1, (ext >> 1) & 0x1, (ext >> 2) & 0x1, + (ext >> 3) & 0x1, (ext >> 4) & 0x1, (ext >> 5) & 0x1, + (ext >> 6) & 0x1, (ext >> 7) & 0x1); + printf ("SER1 uses handshakes %s\n", + (ext & 0x80) ? "DTR/DSR" : "RTS/CTS"); +#else + printf ("User Config Switch %d %d %d %d %d %d %d %d\n", + (ext) & 0x1, (ext >> 1) & 0x1, (ext >> 2) & 0x1, + (ext >> 3) & 0x1, (ext >> 4) & 0x1, (ext >> 5) & 0x1, + (ext >> 6) & 0x1,(ext >> 7) & 0x1); +#endif + printf ("IDE Reset %s\n", (ext & 0x01) ? "asserted" : "not asserted"); + printf ("IRQs:\n"); + printf (" PIIX INTR: %s\n", (irq_reg & 0x80) ? "inactive" : "active"); +#if !defined(CONFIG_MIP405T) + printf (" UART0 IRQ: %s\n", (irq_reg & 0x40) ? "inactive" : "active"); + printf (" UART1 IRQ: %s\n", (irq_reg & 0x20) ? "inactive" : "active"); +#endif + printf (" PIIX SMI: %s\n", (irq_reg & 0x10) ? "inactive" : "active"); + printf (" PIIX INIT: %s\n", (irq_reg & 0x8) ? "inactive" : "active"); + printf (" PIIX NMI: %s\n", (irq_reg & 0x4) ? "inactive" : "active"); +} diff --git a/u-boot/board/mpl/mip405/mip405.h b/u-boot/board/mpl/mip405/mip405.h new file mode 100644 index 0000000..fd7e78a --- /dev/null +++ b/u-boot/board/mpl/mip405/mip405.h @@ -0,0 +1,183 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + */ + /**************************************************************************** + * Global routines used for MIP405 + *****************************************************************************/ +#ifndef __ASSEMBLY__ +/*int switch_cs(unsigned char boot);*/ + +extern int mem_test(unsigned long start, unsigned long ramsize,int mode); + +void user_led0(unsigned char on); + + +#endif +/* timings */ +/* PLD (CS7) */ +#define PLD_BME 0 /* Burst disable */ +#define PLD_TWE 5 /* 5 * 30ns 120ns Waitstates (access=TWT+1+TH) */ +#define PLD_CSN 1 /* Chipselect is driven inactive for 1 Cycle BTW transfers */ +#define PLD_OEN 1 /* Cycles from CS low to OE low */ +#define PLD_WBN 1 /* Cycles from CS low to WE low */ +#define PLD_WBF 1 /* Cycles from WE high to CS high */ +#define PLD_TH 2 /* Number of hold cycles after transfer */ +#define PLD_RE 0 /* Ready disabled */ +#define PLD_SOR 1 /* Sample on Ready disabled */ +#define PLD_BEM 0 /* Byte Write only active on Write cycles */ +#define PLD_PEN 0 /* Parity disable */ +#define PLD_AP ((PLD_BME << 31) + (PLD_TWE << 23) + (PLD_CSN << 18) + (PLD_OEN << 16) + (PLD_WBN << 14) + \ + (PLD_WBF << 12) + (PLD_TH << 9) + (PLD_RE << 8) + (PLD_SOR << 7) + (PLD_BEM << 6) + (PLD_PEN << 5)) + +/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */ +#define PLD_BS 0 /* 1 MByte */ +/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */ +#define PLD_BU 3 /* R/W */ +/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */ +#define PLD_BW 0 /* 16Bit */ +#define PLD_CR ((PER_PLD_ADDR & 0xfff00000) + (PLD_BS << 17) + (PLD_BU << 15) + (PLD_BW << 13)) + + +/* timings */ + +#define PER_BOARD_ADDR (PER_UART1_ADDR+(1024*1024)) +/* Dummy CS to get the board revision */ +#define BOARD_BME 0 /* Burst disable */ +#define BOARD_TWE 255 /* 255 * 30ns 120ns Waitstates (access=TWT+1+TH) */ +#define BOARD_CSN 1 /* Chipselect is driven inactive for 1 Cycle BTW transfers */ +#define BOARD_OEN 1 /* Cycles from CS low to OE low */ +#define BOARD_WBN 1 /* Cycles from CS low to WE low */ +#define BOARD_WBF 1 /* Cycles from WE high to CS high */ +#define BOARD_TH 2 /* Number of hold cycles after transfer */ +#define BOARD_RE 0 /* Ready disabled */ +#define BOARD_SOR 1 /* Sample on Ready disabled */ +#define BOARD_BEM 0 /* Byte Write only active on Write cycles */ +#define BOARD_PEN 0 /* Parity disable */ +#define BOARD_AP ((BOARD_BME << 31) + (BOARD_TWE << 23) + (BOARD_CSN << 18) + (BOARD_OEN << 16) + (BOARD_WBN << 14) + \ + (BOARD_WBF << 12) + (BOARD_TH << 9) + (BOARD_RE << 8) + (BOARD_SOR << 7) + (BOARD_BEM << 6) + (BOARD_PEN << 5)) + +/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */ +#define BOARD_BS 0 /* 1 MByte */ +/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */ +#define BOARD_BU 3 /* R/W */ +/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */ +#define BOARD_BW 0 /* 16Bit */ +#define BOARD_CR ((PER_BOARD_ADDR & 0xfff00000) + (BOARD_BS << 17) + (BOARD_BU << 15) + (BOARD_BW << 13)) + + +/* UART0 CS2 */ +#define UART0_BME 0 /* Burst disable */ +#define UART0_TWE 7 /* 7 * 30ns 210ns Waitstates (access=TWT+1+TH) */ +#define UART0_CSN 1 /* Chipselect is driven inactive for 1 Cycle BTW transfers */ +#define UART0_OEN 1 /* Cycles from CS low to OE low */ +#define UART0_WBN 1 /* Cycles from CS low to WE low */ +#define UART0_WBF 1 /* Cycles from WE high to CS high */ +#define UART0_TH 2 /* Number of hold cycles after transfer */ +#define UART0_RE 0 /* Ready disabled */ +#define UART0_SOR 1 /* Sample on Ready disabled */ +#define UART0_BEM 0 /* Byte Write only active on Write cycles */ +#define UART0_PEN 0 /* Parity disable */ +#define UART0_AP ((UART0_BME << 31) + (UART0_TWE << 23) + (UART0_CSN << 18) + (UART0_OEN << 16) + (UART0_WBN << 14) + \ + (UART0_WBF << 12) + (UART0_TH << 9) + (UART0_RE << 8) + (UART0_SOR << 7) + (UART0_BEM << 6) + (UART0_PEN << 5)) + +/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */ +#define UART0_BS 0 /* 1 MByte */ +/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */ +#define UART0_BU 3 /* R/W */ +/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */ +#define UART0_BW 0 /* 8Bit */ +#define UART0_CR ((PER_UART0_ADDR & 0xfff00000) + (UART0_BS << 17) + (UART0_BU << 15) + (UART0_BW << 13)) + +/* UART1 CS3 */ +#define UART1_AP UART0_AP /* same timing as UART0 */ +#define UART1_CR ((PER_UART1_ADDR & 0xfff00000) + (UART0_BS << 17) + (UART0_BU << 15) + (UART0_BW << 13)) + + +/* Flash CS0 or CS 1 */ +/* 0x7F8FFE80 slowest timing at all... */ +#define FLASH_BME_B 1 /* Burst enable */ +#define FLASH_FWT_B 0x6 /* 6 * 30ns 210ns First Wait Access */ +#define FLASH_BWT_B 0x6 /* 6 * 30ns 210ns Burst Wait Access */ +#define FLASH_BME 0 /* Burst disable */ +#define FLASH_TWE 0xb/* 11 * 30ns 330ns Waitstates (access=TWT+1+TH) */ +#define FLASH_CSN 0 /* Chipselect is driven inactive for 1 Cycle BTW transfers */ +#define FLASH_OEN 1 /* Cycles from CS low to OE low */ +#define FLASH_WBN 1 /* Cycles from CS low to WE low */ +#define FLASH_WBF 1 /* Cycles from WE high to CS high */ +#define FLASH_TH 2 /* Number of hold cycles after transfer */ +#define FLASH_RE 0 /* Ready disabled */ +#define FLASH_SOR 1 /* Sample on Ready disabled */ +#define FLASH_BEM 0 /* Byte Write only active on Write cycles */ +#define FLASH_PEN 0 /* Parity disable */ +/* Access Parameter Register for non Boot */ +#define FLASH_AP ((FLASH_BME << 31) + (FLASH_TWE << 23) + (FLASH_CSN << 18) + (FLASH_OEN << 16) + (FLASH_WBN << 14) + \ + (FLASH_WBF << 12) + (FLASH_TH << 9) + (FLASH_RE << 8) + (FLASH_SOR << 7) + (FLASH_BEM << 6) + (FLASH_PEN << 5)) +/* Access Parameter Register for Boot */ +#define FLASH_AP_B ((FLASH_BME_B << 31) + (FLASH_FWT_B << 26) + (FLASH_BWT_B << 23) + (FLASH_CSN << 18) + (FLASH_OEN << 16) + (FLASH_WBN << 14) + \ + (FLASH_WBF << 12) + (FLASH_TH << 9) + (FLASH_RE << 8) + (FLASH_SOR << 7) + (FLASH_BEM << 6) + (FLASH_PEN << 5)) + +/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */ +#define FLASH_BS FLASH_SIZE_PRELIM /* 4 MByte */ +/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */ +#define FLASH_BU 3 /* R/W */ +/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */ +#define FLASH_BW 1 /* 16Bit */ +/* CR register for Boot */ +#define FLASH_CR_B ((FLASH_BASE_PRELIM & 0xfff00000) + (FLASH_BS << 17) + (FLASH_BU << 15) + (FLASH_BW << 13)) +/* CR register for non Boot */ +#define FLASH_CR ((MULTI_PURPOSE_SOCKET_ADDR & 0xfff00000) + (FLASH_BS << 17) + (FLASH_BU << 15) + (FLASH_BW << 13)) + +/* MPS CS1 or CS0 */ +/* Boot CS: */ +#define MPS_BME_B 1 /* Burst enable */ +#define MPS_FWT_B 0x6/* 6 * 30ns 210ns First Wait Access */ +#define MPS_BWT_B 0x6 /* 6 * 30ns 210ns Burst Wait Access */ +#define MPS_BME 0 /* Burst disable */ +#define MPS_TWE 0xb/* 11 * 30ns 330ns Waitstates (access=TWT+1+TH) */ +#define MPS_CSN 0 /* Chipselect is driven inactive for 1 Cycle BTW transfers */ +#define MPS_OEN 1 /* Cycles from CS low to OE low */ +#define MPS_WBN 1 /* Cycles from CS low to WE low */ +#define MPS_WBF 1 /* Cycles from WE high to CS high */ +#define MPS_TH 2 /* Number of hold cycles after transfer */ +#define MPS_RE 0 /* Ready disabled */ +#define MPS_SOR 1 /* Sample on Ready disabled */ +#define MPS_BEM 0 /* Byte Write only active on Write cycles */ +#define MPS_PEN 0 /* Parity disable */ +/* Access Parameter Register for non Boot */ +#define MPS_AP ((MPS_BME << 31) + (MPS_TWE << 23) + (MPS_CSN << 18) + (MPS_OEN << 16) + (MPS_WBN << 14) + \ + (MPS_WBF << 12) + (MPS_TH << 9) + (MPS_RE << 8) + (MPS_SOR << 7) + (MPS_BEM << 6) + (MPS_PEN << 5)) +/* Access Parameter Register for Boot */ +#define MPS_AP_B ((MPS_BME_B << 31) + (MPS_FWT_B << 26) + (MPS_BWT_B << 23) + (MPS_CSN << 18) + (MPS_OEN << 16) + (MPS_WBN << 14) + \ + (MPS_WBF << 12) + (MPS_TH << 9) + (MPS_RE << 8) + (MPS_SOR << 7) + (MPS_BEM << 6) + (MPS_PEN << 5)) + +/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */ +#define MPS_BS 2 /* 4 MByte */ +#define MPS_BS_B FLASH_SIZE_PRELIM /* 1 MByte */ +/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */ +#define MPS_BU 3 /* R/W */ +/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */ +#define MPS_BW 0 /* 8Bit */ +/* CR register for Boot */ +#define MPS_CR_B ((FLASH_BASE_PRELIM & 0xfff00000) + (MPS_BS_B << 17) + (MPS_BU << 15) + (MPS_BW << 13)) +/* CR register for non Boot */ +#define MPS_CR ((MULTI_PURPOSE_SOCKET_ADDR & 0xfff00000) + (MPS_BS << 17) + (MPS_BU << 15) + (MPS_BW << 13)) diff --git a/u-boot/board/mpl/pati/Makefile b/u-boot/board/mpl/pati/Makefile new file mode 100644 index 0000000..937dfec --- /dev/null +++ b/u-boot/board/mpl/pati/Makefile @@ -0,0 +1,54 @@ +# +# (C) Copyright 2001-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)../common) +endif + +LIB = $(obj)lib$(BOARD).o + +COBJS := pati.o ../common/flash.o cmd_pati.o ../common/common_util.o +#### cmd_pati.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/board/mpl/pati/cmd_pati.c b/u-boot/board/mpl/pati/cmd_pati.c new file mode 100644 index 0000000..aba11d5 --- /dev/null +++ b/u-boot/board/mpl/pati/cmd_pati.c @@ -0,0 +1,449 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * Adapted for PATI + */ + +#include <common.h> +#include <command.h> +#define PLX9056_LOC +#include "plx9056.h" +#include "pati.h" +#include "pci_eeprom.h" + +extern void show_pld_regs(void); +extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + +extern void user_led0(int led_on); +extern void user_led1(int led_on); + +/* ------------------------------------------------------------------------- */ +#if defined(CONFIG_SYS_PCI_CON_DEVICE) +extern void pci_con_disc(void); +extern void pci_con_connect(void); +#endif + +/****************************************************************************** + * Eeprom Support + ******************************************************************************/ +unsigned long get32(unsigned long addr) +{ + unsigned long *p=(unsigned long *)addr; + return *p; +} + +void set32(unsigned long addr,unsigned long data) +{ + unsigned long *p=(unsigned long *)addr; + *p=data; +} + +#define PCICFG_GET_REG(x) (get32((x) + PCI_CONFIG_BASE)) +#define PCICFG_SET_REG(x,y) (set32((x) + PCI_CONFIG_BASE,(y))) + + +/****************************************************************************** + * reload_pci_eeprom + ******************************************************************************/ + +static void reload_pci_eeprom(void) +{ + unsigned long reg; + /* Set Bit 29 and clear it again */ + reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT); + udelay(1); + /* set it*/ + reg|=(1<<29); + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg); + /* EECLK @ 33MHz = 125kHz + * -> extra long load = 32 * 16bit = 512Bit @ 125kHz = 4.1msec + * use 20msec + */ + udelay(20000); /* wait 20ms */ + reg &= ~(1<<29); /* set it low */ + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg); + udelay(1); /* wait some time */ +} + +/****************************************************************************** + * clock_pci_eeprom + ******************************************************************************/ + +static void clock_pci_eeprom(void) +{ + unsigned long reg; + /* clock is low, data is valid */ + reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT); + udelay(1); + /* set clck high */ + reg|=(1<<24); + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg); + udelay(1); /* wait some time */ + reg &= ~(1<<24); /* set clock low */ + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg); + udelay(1); /* wait some time */ +} + +/****************************************************************************** + * send_pci_eeprom_cmd + ******************************************************************************/ +static void send_pci_eeprom_cmd(unsigned long cmd, unsigned char len) +{ + unsigned long reg; + int i; + reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT); + /* Clear all EEPROM bits */ + reg &= ~(0xF << 24); + /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */ + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg); + udelay(1); /* wait some time */ + /* Enable EEPROM Chip Select */ + reg |= (1 << 25); + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg); + /* Send EEPROM command - one bit at a time */ + for (i = (int)(len-1); i >= 0; i--) { + /* Check if current bit is 0 or 1 */ + if (cmd & (1 << i)) + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,(reg | (1<<26))); + else + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg); + clock_pci_eeprom(); + } +} + +/****************************************************************************** + * write_pci_eeprom_offs + ******************************************************************************/ +static void write_pci_eeprom_offs(unsigned short offset, unsigned short value) +{ + unsigned long reg; + int bitpos, cmdshft, cmdlen, timeout; + /* we're using the Eeprom 93CS66 */ + cmdshft = 2; + cmdlen = EE66_CMD_LEN; + /* Send Write_Enable command to EEPROM */ + send_pci_eeprom_cmd((EE_WREN << cmdshft),cmdlen); + /* Send EEPROM Write command and offset to EEPROM */ + send_pci_eeprom_cmd((EE_WRITE << cmdshft) | (offset / 2),cmdlen); + reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT); + /* Clear all EEPROM bits */ + reg &= ~(0xF << 24); + /* Make sure EEDO Input is disabled for some PLX chips */ + reg &= ~(1 << 31); + /* Enable EEPROM Chip Select */ + reg |= (1 << 25); + /* Write 16-bit value to EEPROM - one bit at a time */ + for (bitpos = 15; bitpos >= 0; bitpos--) { + /* Get bit value and shift into result */ + if (value & (1 << bitpos)) + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,(reg | (1<<26))); + else + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg ); + clock_pci_eeprom(); + } /* for */ + /* Deselect Chip */ + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(1 << 25)); + /* Re-select Chip */ + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg | (1 << 25)); + /* A small delay is needed to let EEPROM complete */ + timeout = 0; + do { + udelay(10); + reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT); + timeout++; + } while (((reg & (1 << 27)) == 0) && timeout < 20000); + /* Send Write_Disable command to EEPROM */ + send_pci_eeprom_cmd((EE_WDS << cmdshft),cmdlen); + /* Clear Chip Select and all other EEPROM bits */ + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(0xF << 24)); +} + + +/****************************************************************************** + * read_pci_eeprom_offs + ******************************************************************************/ +static void read_pci_eeprom_offs(unsigned short offset, unsigned short *pvalue) +{ + unsigned long reg; + int bitpos, cmdshft, cmdlen; + /* we're using the Eeprom 93CS66 */ + cmdshft = 2; + cmdlen = EE66_CMD_LEN; + /* Send EEPROM read command and offset to EEPROM */ + send_pci_eeprom_cmd((EE_READ << cmdshft) | (offset / 2),cmdlen); + /* Set EEPROM write output bit */ + reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT); + /* Set EEDO Input enable */ + reg |= (1 << 31); + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg | (1 << 26)); + /* Get 16-bit value from EEPROM - one bit at a time */ + for (bitpos = 0; bitpos < 16; bitpos++) { + clock_pci_eeprom(); + udelay(10); + reg=PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT); + /* Get bit value and shift into result */ + if (reg & (1 << 27)) + *pvalue = (unsigned short)((*pvalue << 1) | 1); + else + *pvalue = (unsigned short)(*pvalue << 1); + } + /* Clear EEDO Input enable */ + reg &= ~(1 << 31); + /* Clear Chip Select and all other EEPROM bits */ + PCICFG_SET_REG(PCI9056_EEPROM_CTRL_STAT,reg & ~(0xF << 24)); +} + + +/****************************************************************************** + * EEPROM read/writes +******************************************************************************/ + +#undef EEPROM_DBG +static int pati_pci_eeprom_erase(void) +{ + int i; + printf("Erasing EEPROM "); + for( i=0; i < PATI_EEPROM_LAST_OFFSET; i+=2) { + write_pci_eeprom_offs(i,0xffff); + if((i%0x10)) + printf("."); + } + printf("\nDone\n"); + return 0; +} + +static int pati_pci_eeprom_prg(void) +{ + int i; + i=0; + printf("Programming EEPROM "); + while(pati_eeprom[i].offset<0xffff) { + write_pci_eeprom_offs(pati_eeprom[i].offset,pati_eeprom[i].value); + #ifdef EEPROM_DBG + printf("0x%04X: 0x%04X\n",pati_eeprom[i].offset, pati_eeprom[i].value); + #else + if((i%0x10)) + printf("."); + #endif + i++; + } + printf("\nDone\n"); + return 0; +} + +static int pati_pci_eeprom_write(unsigned short offset, unsigned long addr, unsigned short size) +{ + int i; + unsigned short value; + unsigned short *buffer =(unsigned short *)addr; + if((offset + size) > PATI_EEPROM_LAST_OFFSET) { + size = PATI_EEPROM_LAST_OFFSET - offset; + } + printf("Write To EEPROM from 0x%lX to 0x%X 0x%X words\n", addr, offset, size/2); + for( i = offset; i< (offset + size); i+=2) { + value = *buffer++; + write_pci_eeprom_offs(i,value); + #ifdef EEPROM_DBG + printf("0x%04X: 0x%04X\n",i, value); + #else + if((i%0x10)) + printf("."); + #endif + } + printf("\nDone\n"); + return 0; +} + +static int pati_pci_eeprom_read(unsigned short offset, unsigned long addr, unsigned short size) +{ + int i; + unsigned short value = 0; + unsigned short *buffer =(unsigned short *)addr; + if((offset + size) > PATI_EEPROM_LAST_OFFSET) { + size = PATI_EEPROM_LAST_OFFSET - offset; + } + printf("Read from EEPROM from 0x%X to 0x%lX 0x%X words\n", offset, addr, size/2); + for( i = offset; i< (offset + size); i+=2) { + read_pci_eeprom_offs(i,&value); + *buffer++=value; + #ifdef EEPROM_DBG + printf("0x%04X: 0x%04X\n",i, value); + #else + if((i%0x10)) + printf("."); + #endif + } + printf("\nDone\n"); + return 0; +} + +/****************************************************************************** + * PCI Bridge Registers Dump +*******************************************************************************/ +static void display_pci_regs(void) +{ + printf(" PCI9056_SPACE0_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_RANGE)); + printf(" PCI9056_SPACE0_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_REMAP)); + printf(" PCI9056_LOCAL_DMA_ARBIT %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_DMA_ARBIT)); + printf(" PCI9056_ENDIAN_DESC %08lX\n",PCICFG_GET_REG(PCI9056_ENDIAN_DESC)); + printf(" PCI9056_EXP_ROM_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_RANGE)); + printf(" PCI9056_EXP_ROM_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_REMAP)); + printf(" PCI9056_SPACE0_ROM_DESC %08lX\n",PCICFG_GET_REG(PCI9056_SPACE0_ROM_DESC)); + printf(" PCI9056_DM_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_DM_RANGE)); + printf(" PCI9056_DM_MEM_BASE %08lX\n",PCICFG_GET_REG(PCI9056_DM_MEM_BASE)); + printf(" PCI9056_DM_IO_BASE %08lX\n",PCICFG_GET_REG(PCI9056_DM_IO_BASE)); + printf(" PCI9056_DM_PCI_MEM_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_DM_PCI_MEM_REMAP)); + printf(" PCI9056_DM_PCI_IO_CONFIG %08lX\n",PCICFG_GET_REG(PCI9056_DM_PCI_IO_CONFIG)); + printf(" PCI9056_SPACE1_RANGE %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_RANGE)); + printf(" PCI9056_SPACE1_REMAP %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_REMAP)); + printf(" PCI9056_SPACE1_DESC %08lX\n",PCICFG_GET_REG(PCI9056_SPACE1_DESC)); + printf(" PCI9056_DM_DAC %08lX\n",PCICFG_GET_REG(PCI9056_DM_DAC)); + printf(" PCI9056_MAILBOX0 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX0)); + printf(" PCI9056_MAILBOX1 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX1)); + printf(" PCI9056_MAILBOX2 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX2)); + printf(" PCI9056_MAILBOX3 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX3)); + printf(" PCI9056_MAILBOX4 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX4)); + printf(" PCI9056_MAILBOX5 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX5)); + printf(" PCI9056_MAILBOX6 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX6)); + printf(" PCI9056_MAILBOX7 %08lX\n",PCICFG_GET_REG(PCI9056_MAILBOX7)); + printf(" PCI9056_PCI_TO_LOC_DBELL %08lX\n",PCICFG_GET_REG(PCI9056_PCI_TO_LOC_DBELL)); + printf(" PCI9056_LOC_TO_PCI_DBELL %08lX\n",PCICFG_GET_REG(PCI9056_LOC_TO_PCI_DBELL)); + printf(" PCI9056_INT_CTRL_STAT %08lX\n",PCICFG_GET_REG(PCI9056_INT_CTRL_STAT)); + printf(" PCI9056_EEPROM_CTRL_STAT %08lX\n",PCICFG_GET_REG(PCI9056_EEPROM_CTRL_STAT)); + printf(" PCI9056_PERM_VENDOR_ID %08lX\n",PCICFG_GET_REG(PCI9056_PERM_VENDOR_ID)); + printf(" PCI9056_REVISION_ID %08lX\n",PCICFG_GET_REG(PCI9056_REVISION_ID)); + printf(" \n"); + printf(" PCI9056_VENDOR_ID %08lX\n",PCICFG_GET_REG(PCI9056_VENDOR_ID)); + printf(" PCI9056_COMMAND %08lX\n",PCICFG_GET_REG(PCI9056_COMMAND)); + printf(" PCI9056_REVISION %08lX\n",PCICFG_GET_REG(PCI9056_REVISION)); + printf(" PCI9056_CACHE_SIZE %08lX\n",PCICFG_GET_REG(PCI9056_CACHE_SIZE)); + printf(" PCI9056_RTR_BASE %08lX\n",PCICFG_GET_REG(PCI9056_RTR_BASE)); + printf(" PCI9056_RTR_IO_BASE %08lX\n",PCICFG_GET_REG(PCI9056_RTR_IO_BASE)); + printf(" PCI9056_LOCAL_BASE0 %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_BASE0)); + printf(" PCI9056_LOCAL_BASE1 %08lX\n",PCICFG_GET_REG(PCI9056_LOCAL_BASE1)); + printf(" PCI9056_UNUSED_BASE1 %08lX\n",PCICFG_GET_REG(PCI9056_UNUSED_BASE1)); + printf(" PCI9056_UNUSED_BASE2 %08lX\n",PCICFG_GET_REG(PCI9056_UNUSED_BASE2)); + printf(" PCI9056_CIS_PTR %08lX\n",PCICFG_GET_REG(PCI9056_CIS_PTR)); + printf(" PCI9056_SUB_ID %08lX\n",PCICFG_GET_REG(PCI9056_SUB_ID)); + printf(" PCI9056_EXP_ROM_BASE %08lX\n",PCICFG_GET_REG(PCI9056_EXP_ROM_BASE)); + printf(" PCI9056_CAP_PTR %08lX\n",PCICFG_GET_REG(PCI9056_CAP_PTR)); + printf(" PCI9056_INT_LINE %08lX\n",PCICFG_GET_REG(PCI9056_INT_LINE)); + printf(" PCI9056_PM_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_PM_CAP_ID)); + printf(" PCI9056_PM_CSR %08lX\n",PCICFG_GET_REG(PCI9056_PM_CSR)); + printf(" PCI9056_HS_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_HS_CAP_ID)); + printf(" PCI9056_VPD_CAP_ID %08lX\n",PCICFG_GET_REG(PCI9056_VPD_CAP_ID)); + printf(" PCI9056_VPD_DATA %08lX\n",PCICFG_GET_REG(PCI9056_VPD_DATA)); +} + + +int do_pati(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (strcmp(argv[1], "info") == 0) + { + show_pld_regs(); + return 0; + } + if (strcmp(argv[1], "pci") == 0) + { + display_pci_regs(); + return 0; + } + if (strcmp(argv[1], "led") == 0) + { + int led_nr,led_on; + led_nr = (int)simple_strtoul(argv[2], NULL, 10); + led_on = (int)simple_strtoul(argv[3], NULL, 10); + if(!led_nr) + user_led0(led_on); + else + user_led1(led_on); + return 0; + } +#if defined(CONFIG_SYS_PCI_CON_DEVICE) + if (strcmp(argv[1], "con") == 0) { + pci_con_connect(); + return 0; + } + if (strcmp(argv[1], "disc") == 0) { + pci_con_disc(); + return 0; + } +#endif + if (strcmp(argv[1], "eeprom") == 0) { + unsigned long addr; + int size, offset; + offset = 0; + size = PATI_EEPROM_LAST_OFFSET; + if(argc>2) { + if(argc>3) { + addr = simple_strtoul(argv[3], NULL, 16); + if(argc>4) + offset = (int) simple_strtoul(argv[4], NULL, 16); + if(argc>5) + size = (int) simple_strtoul(argv[5], NULL, 16); + if (strcmp(argv[2], "read") == 0) { + return (pati_pci_eeprom_read(offset, addr, size)); + } + if (strcmp(argv[2], "write") == 0) { + return (pati_pci_eeprom_write(offset, addr, size)); + } + } + if (strcmp(argv[2], "prg") == 0) { + return (pati_pci_eeprom_prg()); + } + if (strcmp(argv[2], "era") == 0) { + return (pati_pci_eeprom_erase()); + } + if (strcmp(argv[2], "reload") == 0) { + reload_pci_eeprom(); + return 0; + } + + + } + } + + return (do_mplcommon(cmdtp, flag, argc, argv)); +} + +U_BOOT_CMD( + pati, 8, 1, do_pati, + "PATI specific Cmds", + "info - displays board information\n" + "pati pci - displays PCI registers\n" + "pati led <nr> <on> \n" + " - switch LED <nr> <on>\n" + "pati flash mem [SrcAddr]\n" + " - updates U-Boot with image in memory\n" + "pati eeprom <cmd> - PCI EEPROM sub-system\n" + " read <addr> <offset> <size>\n" + " - read PCI EEPROM to <addr> from <offset> <size> words\n" + " write <addr> <offset> <size>\n" + " - write PCI EEPROM from <addr> to <offset> <size> words\n" + " prg - programm PCI EEPROM with default values\n" + " era - erase PCI EEPROM (write all word to 0xffff)\n" + " reload- Reload PCI Bridge with EEPROM Values\n" + " NOTE: <addr> must start on word boundary\n" + " <offset> and <size> must be even byte values" +); + +/* ------------------------------------------------------------------------- */ diff --git a/u-boot/board/mpl/pati/pati.c b/u-boot/board/mpl/pati/pati.c new file mode 100644 index 0000000..7f1164a --- /dev/null +++ b/u-boot/board/mpl/pati/pati.c @@ -0,0 +1,616 @@ +/* + * (C) Copyright 2003 + * Martin Winistoerfer, martinwinistoerfer@gmx.ch. + * Atapted for PATI + * Denis Peter, d.peter@mpl.ch + * 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 + */ + +/*********************************************************************************** + * Bits for the SDRAM controller + * ----------------------------- + * + * CAL: CAS Latency. If cleared to 0 (default) the SDRAM controller asserts TA# on + * the 2nd Clock after ACTIVE command (CAS Latency = 2). If set to 1 the SDRAM + * controller asserts TA# on the 3rd Clock after ACTIVE command (CAS Latency = 3). + * RCD: RCD ACTIVE to READ or WRITE Delay (Ras to Cas Delay). If cleared 0 (default) + * tRCD of the SDRAM must equal or less 25ns. If set to 1 tRCD must be equal or less 50ns. + * WREC:Write Recovery. If cleared 0 (default) tWR of the SDRAM must equal or less 25ns. + * If set to 1 tWR must be equal or less 50ns. + * RP: Precharge Command Time. If cleared 0 (default) tRP of the SDRAM must equal or less + * 25ns. If set to 1 tRP must be equal or less 50ns. + * RC: Auto Refresh to Active Time. If cleared 0 (default) tRC of the SDRAM must equal + * or less 75ns. If set to 1 tRC must be equal or less 100ns. + * LMR: Bit to set the Mode Register of the SDRAM. If set, the next access to the SDRAM + * is the Load Mode Register Command. + * IIP: Init in progress. Set to 1 for starting the init sequence + * (Precharge All). As long this bit is set, the Precharge All is still in progress. + * After command has completed, wait at least for 8 refresh (200usec) before proceed. + **********************************************************************************/ + +#include <common.h> +#include <mpc5xx.h> +#include <stdio_dev.h> +#include <pci_ids.h> +#define PLX9056_LOC +#include "plx9056.h" +#include "pati.h" + +#if defined(__APPLE__) +/* Leading underscore on symbols */ +# define SYM_CHAR "_" +#else /* No leading character on symbols */ +# define SYM_CHAR +#endif + +#undef SDRAM_DEBUG +/* + * Macros to generate global absolutes. + */ +#define GEN_SYMNAME(str) SYM_CHAR #str +#define GEN_VALUE(str) #str +#define GEN_ABS(name, value) \ + asm (".globl " GEN_SYMNAME(name)); \ + asm (GEN_SYMNAME(name) " = " GEN_VALUE(value)) + + +/************************************************************************ + * Early debug routines + */ +void write_hex (unsigned char i) +{ + char cc; + + cc = i >> 4; + cc &= 0xf; + if (cc > 9) + serial_putc (cc + 55); + else + serial_putc (cc + 48); + cc = i & 0xf; + if (cc > 9) + serial_putc (cc + 55); + else + serial_putc (cc + 48); +} + +#if defined(SDRAM_DEBUG) + +void write_4hex (unsigned long val) +{ + write_hex ((unsigned char) (val >> 24)); + write_hex ((unsigned char) (val >> 16)); + write_hex ((unsigned char) (val >> 8)); + write_hex ((unsigned char) val); +} + +#endif + +unsigned long in32(unsigned long addr) +{ + unsigned long *p=(unsigned long *)addr; + return *p; +} + +void out32(unsigned long addr,unsigned long data) +{ + unsigned long *p=(unsigned long *)addr; + *p=data; +} + +typedef struct { + unsigned short boardtype; /* Board revision and Population Options */ + unsigned char cal; /* cas Latency 0:CAL=2 1:CAL=3 */ + unsigned char rcd; /* ras to cas delay 0:<25ns 1:<50ns*/ + unsigned char wrec; /* write recovery 0:<25ns 1:<50ns */ + unsigned char pr; /* Precharge Command Time 0:<25ns 1:<50ns */ + unsigned char rc; /* Auto Refresh to Active Time 0:<75ns 1:<100ns */ + unsigned char sz; /* log binary => Size = (4MByte<<sz) 5 = 128, 4 = 64, 3 = 32, 2 = 16, 1=8 */ +} sdram_t; + +const sdram_t sdram_table[] = { + { 0x0000, /* PATI Rev A, 16MByte -1 Board */ + 1, /* Case Latenty = 3 */ + 0, /* ras to cas delay 0 (20ns) */ + 0, /* write recovery 0:<25ns 1:<50ns*/ + 0, /* Precharge Command Time 0 (20ns) */ + 0, /* Auto Refresh to Active Time 0 (68) */ + 2 /* log binary => Size 2 = 16MByte, 1=8 */ + }, + { 0xffff, /* terminator */ + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff } +}; + + +extern int mem_test (unsigned long start, unsigned long ramsize, int quiet); + +/* + * Get RAM size. + */ +phys_size_t initdram(int board_type) +{ + unsigned char board_rev; + unsigned long reg; + unsigned long lmr; + int i,timeout; + +#if defined(SDRAM_DEBUG) + reg=in32(PLD_CONFIG_BASE+PLD_PART_ID); + puts("\n\nSYSTEM part 0x"); write_4hex(SYSCNTR_PART(reg)); + puts(" Vers 0x"); write_4hex(SYSCNTR_ID(reg)); + puts("\nSDRAM part 0x"); write_4hex(SDRAM_PART(reg)); + puts(" Vers 0x"); write_4hex(SDRAM_ID(reg)); + reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); + puts("\nBoard rev. 0x"); write_4hex(SYSCNTR_BREV(reg)); + putc('\n'); +#endif + reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); + board_rev=(unsigned char)(SYSCNTR_BREV(reg)); + i=0; + while(1) { + if(sdram_table[i].boardtype==0xffff) { + puts("ERROR, found no table for Board 0x"); + write_hex(board_rev); + while(1); + } + if(sdram_table[i].boardtype==(unsigned char)board_rev) + break; + i++; + } + /* Set CAL, RCD, WREQ, PR and RC Bits */ +#if defined(SDRAM_DEBUG) + puts("Set CAL, RCD, WREQ, PR and RC Bits\n"); +#endif + /* mask bits */ + reg &= ~(SET_REG_BIT(1,SDRAM_CAL) | SET_REG_BIT(1,SDRAM_RCD) | SET_REG_BIT(1,SDRAM_WREQ) | + SET_REG_BIT(1,SDRAM_PR) | SET_REG_BIT(1,SDRAM_RC) | SET_REG_BIT(1,SDRAM_LMR) | + SET_REG_BIT(1,SDRAM_IIP) | SET_REG_BIT(1,SDRAM_RES0)); + /* set bits */ + reg |= (SET_REG_BIT(sdram_table[i].cal,SDRAM_CAL) | + SET_REG_BIT(sdram_table[i].rcd,SDRAM_RCD) | + SET_REG_BIT(sdram_table[i].wrec,SDRAM_WREQ) | + SET_REG_BIT(sdram_table[i].pr,SDRAM_PR) | + SET_REG_BIT(sdram_table[i].rc,SDRAM_RC)); + + out32(PLD_CONFIG_BASE+PLD_BOARD_TIMING,reg); + /* step 2 set IIP */ +#if defined(SDRAM_DEBUG) + puts("step 2 set IIP\n"); +#endif + /* step 2 set IIP */ + reg |= SET_REG_BIT(1,SDRAM_IIP); + timeout=0; + while (timeout!=0xffff) { + __asm__ volatile("eieio"); + reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); + if((reg & SET_REG_BIT(1,SDRAM_IIP))==0) + break; + timeout++; + udelay(1); + } + /* wait for at least 8 refresh */ + udelay(1000); + /* set LMR */ + reg |= SET_REG_BIT(1,SDRAM_LMR); + out32(PLD_CONFIG_BASE+PLD_BOARD_TIMING,reg); + __asm__ volatile("eieio"); + lmr=0x00000002; /* sequential burst 4 data */ + if(sdram_table[i].cal==1) + lmr|=0x00000030; /* cal = 3 */ + else + lmr|=0000000020; /* cal = 2 */ + /* rest standard operation programmed write burst length */ + /* we have a x32 bit bus to the SDRAM, so shift the addr with 2 */ + lmr<<=2; + in32(CONFIG_SYS_SDRAM_BASE + lmr); + /* ok, we're done, return SDRAM size */ + return ((0x400000 << sdram_table[i].sz)); /* log2 value of 4MByte */ +} + + +void set_flash_vpp(int ext_vpp, int ext_wp, int int_vpp) +{ + unsigned long reg; + reg=in32(PLD_CONF_REG2+PLD_CONFIG_BASE); + reg &= ~(SET_REG_BIT(1,SYSCNTR_CPU_VPP) | + SET_REG_BIT(1,SYSCNTR_FL_VPP) | + SET_REG_BIT(1,SYSCNTR_FL_WP)); + + reg |= (SET_REG_BIT(int_vpp,SYSCNTR_CPU_VPP) | + SET_REG_BIT(ext_vpp,SYSCNTR_FL_VPP) | + SET_REG_BIT(ext_wp,SYSCNTR_FL_WP)); + out32(PLD_CONF_REG2+PLD_CONFIG_BASE,reg); + udelay(100); +} + + +void show_pld_regs(void) +{ + unsigned long reg,reg1; + reg=in32(PLD_CONFIG_BASE+PLD_PART_ID); + printf("\nSYSTEM part %ld, Vers %ld\n",SYSCNTR_PART(reg),SYSCNTR_ID(reg)); + printf("SDRAM part %ld, Vers %ld\n",SDRAM_PART(reg),SDRAM_ID(reg)); + reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); + printf("Board rev. %c\n",(char) (SYSCNTR_BREV(reg)+'A')); + printf("Waitstates %ld\n",GET_SYSCNTR_FLWAIT(reg)); + printf("SDRAM: CAL=%ld RCD=%ld WREQ=%ld PR=%ld\n RC=%ld LMR=%ld IIP=%ld\n", + GET_REG_BIT(reg,SDRAM_CAL),GET_REG_BIT(reg,SDRAM_RCD), + GET_REG_BIT(reg,SDRAM_WREQ),GET_REG_BIT(reg,SDRAM_PR), + GET_REG_BIT(reg,SDRAM_RC),GET_REG_BIT(reg,SDRAM_LMR), + GET_REG_BIT(reg,SDRAM_IIP)); + reg=in32(PLD_CONFIG_BASE+PLD_CONF_REG1); + reg1=in32(PLD_CONFIG_BASE+PLD_CONF_REG2); + printf("HW Config: FLAG=%ld IP=%ld index=%ld PRPM=%ld\n ICW=%ld ISB=%ld BDIS=%ld PCIM=%ld\n", + GET_REG_BIT(reg,SYSCNTR_FLAG),GET_REG_BIT(reg,SYSCNTR_IP), + GET_SYSCNTR_BOOTIND(reg),GET_REG_BIT(reg,SYSCNTR_PRM), + GET_REG_BIT(reg,SYSCNTR_ICW),GET_SYSCNTR_ISB(reg), + GET_REG_BIT(reg1,SYSCNTR_BDIS),GET_REG_BIT(reg1,SYSCNTR_PCIM)); + printf("Switches: MUX=%ld PCI_DIS=%ld Boot_EN=%ld Config=%ld\n",GET_SDRAM_MUX(reg), + GET_REG_BIT(reg,SDRAM_PDIS),GET_REG_BIT(reg1,SYSCNTR_BOOTEN), + GET_SYSCNTR_CFG(reg1)); + printf("Misc: RIP=%ld CPU_VPP=%ld FLSH_VPP=%ld FLSH_WP=%ld\n\n", + GET_REG_BIT(reg,SDRAM_RIP),GET_REG_BIT(reg1,SYSCNTR_CPU_VPP), + GET_REG_BIT(reg1,SYSCNTR_FL_VPP),GET_REG_BIT(reg1,SYSCNTR_FL_WP)); +} + + +/**************************************************************** + * Setting IOs + * ----------- + * GPIO6 is User LED1 + * GPIO7 is Interrupt PLX (Output) + * GPIO5 is User LED0 + * GPIO2 is PLX USERi (Output) + * GPIO1 is PLX Interrupt (Input) + ****************************************************************/ + void init_ios(void) + { + volatile immap_t * immr = (immap_t *) CONFIG_SYS_IMMR; + volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; + unsigned long reg; + reg=sysconf->sc_sgpiocr; /* Data direction register */ + reg &= ~0x67000000; + reg |= 0x27000000; /* set outpupts */ + sysconf->sc_sgpiocr=reg; /* Data direction register */ + reg=sysconf->sc_sgpiodt2; /* Data register */ + /* set output to 0 */ + reg &= ~0x27000000; + /* set IRQ and USERi to 1 */ + reg |= 0x28000000; + sysconf->sc_sgpiodt2=reg; /* Data register */ +} + +void user_led0(int led_on) +{ + volatile immap_t * immr = (immap_t *) CONFIG_SYS_IMMR; + volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; + unsigned long reg; + reg=sysconf->sc_sgpiodt2; /* Data register */ + if(led_on) /* set output to 1 */ + reg |= 0x04000000; + else + reg &= ~0x04000000; + sysconf->sc_sgpiodt2=reg; /* Data register */ +} + +void user_led1(int led_on) +{ + volatile immap_t * immr = (immap_t *) CONFIG_SYS_IMMR; + volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; + unsigned long reg; + reg=sysconf->sc_sgpiodt2; /* Data register */ + if(led_on) /* set output to 1 */ + reg |= 0x02000000; + else + reg &= ~0x02000000; + sysconf->sc_sgpiodt2=reg; /* Data register */ +} + + +/**************************************************************** + * Last Stage Init + ****************************************************************/ +int last_stage_init (void) +{ + init_ios(); + return 0; +} + +/**************************************************************** + * Check the board + ****************************************************************/ + +#define BOARD_NAME "PATI" + +int checkboard (void) +{ + char s[50]; + ulong reg; + char rev; + int i; + + puts ("\nBoard: "); + reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); + rev=(char)(SYSCNTR_BREV(reg)+'A'); + i = getenv_f("serial#", s, 32); + if ((i == -1)) { + puts ("### No HW ID - assuming " BOARD_NAME); + printf(" Rev. %c\n",rev); + } + else { + s[sizeof(BOARD_NAME)-1] = 0; + printf ("%s-1 Rev %c SN: %s\n", s,rev, + &s[sizeof(BOARD_NAME)]); + } + set_flash_vpp(1,0,0); /* set Flash VPP */ + return 0; +} + + +#ifdef CONFIG_SYS_PCI_CON_DEVICE +/************************************************************************ + * PCI Communication + * + * Alive (Pinging): + * ---------------- + * PCI Host sends message ALIVE, Local acknowledges with ALIVE + * + * PCI_CON console over PCI: + * ------------------------- + * Local side: + * - uses PCI9056_LOC_TO_PCI_DBELL register to signal that + * data is avaible (PCIMSG_CONN) + * - uses PCI9056_MAILBOX1 to send data + * - uses PCI9056_MAILBOX0 to receive data + * PCI side: + * - uses PCI9056_PCI_TO_LOC_DBELL register to signal that + * data is avaible (PCIMSG_CONN) + * - uses PCI9056_MAILBOX0 to send data + * - uses PCI9056_MAILBOX1 to receive data + * + * How it works: + * Send: + * - check if PCICON_TRANSMIT_REG is empty + * - write data or'ed with 0x80000000 into the PCICON_TRANSMIT_REG + * - write PCIMSG_CONN into the PCICON_DBELL_REG to signal a data + * is waiting + * Receive: + * - get an interrupt via the PCICON_ACK_REG register message + * PCIMSG_CONN + * - write the data from the PCICON_RECEIVE_REG into the receive + * buffer and if the receive buffer is not full, clear the + * PCICON_RECEIVE_REG (this allows the counterpart to write more data) + * - Clear the interrupt by writing 0xFFFFFFFF to the PCICON_ACK_REG + * + * The PCICON_RECEIVE_REG must be cleared by the routine which reads + * the receive buffer if the buffer is not full any more + * + */ + +#undef PCI_CON_DEBUG + +#ifdef PCI_CON_DEBUG +#define PCI_CON_PRINTF(fmt,args...) serial_printf (fmt ,##args) +#else +#define PCI_CON_PRINTF(fmt,args...) +#endif + + +/********************************************************* + * we work only with a receive buffer on eiter side. + * Transmit buffer is free, if mailbox is cleared. + * Transmit character is or'ed with 0x80000000 + * PATI receive register MAILBOX0 + * PATI transmit register MAILBOX1 + *********************************************************/ +#define PCICON_RECEIVE_REG PCI9056_MAILBOX0 +#define PCICON_TRANSMIT_REG PCI9056_MAILBOX1 +#define PCICON_DBELL_REG PCI9056_LOC_TO_PCI_DBELL +#define PCICON_ACK_REG PCI9056_PCI_TO_LOC_DBELL + + +#define PCIMSG_ALIVE 0x1 +#define PCIMSG_CONN 0x2 +#define PCIMSG_DISC 0x3 +#define PCIMSG_CON_DATA 0x5 + + +#define PCICON_GET_REG(x) (in32(x + PCI_CONFIG_BASE)) +#define PCICON_SET_REG(x,y) (out32(x + PCI_CONFIG_BASE,y)) +#define PCICON_TX_FLAG 0x80000000 + + +#define REC_BUFFER_SIZE 0x100 +int recbuf[REC_BUFFER_SIZE]; +static int r_ptr = 0; +int w_ptr; +struct stdio_dev pci_con_dev; +int conn=0; +int buff_full=0; + +void pci_con_put_it(const char c) +{ + /* Test for completition */ + unsigned long reg; + do { + reg=PCICON_GET_REG(PCICON_TRANSMIT_REG); + }while(reg); + reg=PCICON_TX_FLAG + c; + PCICON_SET_REG(PCICON_TRANSMIT_REG,reg); + PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_CON_DATA); +} + +void pci_con_putc(const char c) +{ + pci_con_put_it(c); + if(c == '\n') + pci_con_put_it('\r'); +} + + +int pci_con_getc(void) +{ + int res; + int diff; + while(r_ptr==(volatile int)w_ptr); + res=recbuf[r_ptr++]; + if(r_ptr==REC_BUFFER_SIZE) + r_ptr=0; + if(w_ptr<r_ptr) + diff=r_ptr+REC_BUFFER_SIZE-w_ptr; + else + diff=r_ptr-w_ptr; + if((diff<(REC_BUFFER_SIZE-4)) && buff_full) { + /* clear Mail box */ + buff_full=0; + PCICON_SET_REG(PCICON_RECEIVE_REG,0L); + } + return res; +} + +int pci_con_tstc(void) +{ + if(r_ptr==(volatile int)w_ptr) + return 0; + return 1; +} + +void pci_con_puts (const char *s) +{ + while (*s) { + pci_con_putc(*s); + ++s; + } +} + +void pci_con_init (void) +{ + w_ptr = 0; + r_ptr = 0; + PCICON_SET_REG(PCICON_RECEIVE_REG,0L); + conn=1; +} + +/******************************************* + * IRQ routine + ******************************************/ +int pci_dorbell_irq(void) +{ + unsigned long reg,data; + int diff; + reg=PCICON_GET_REG(PCI9056_INT_CTRL_STAT); + PCI_CON_PRINTF(" PCI9056_INT_CTRL_STAT = %08lX\n",reg); + if(reg & (1<<20) ) { + /* read doorbell */ + reg=PCICON_GET_REG(PCICON_ACK_REG); + switch(reg) { + case PCIMSG_ALIVE: + PCI_CON_PRINTF(" Alive\n"); + PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_ALIVE); + break; + case PCIMSG_CONN: + PCI_CON_PRINTF(" Conn %d",conn); + w_ptr = 0; + r_ptr = 0; + buff_full=0; + PCICON_SET_REG(PCICON_RECEIVE_REG,0L); + conn=1; + PCI_CON_PRINTF(" ... %d\n",conn); + break; + case PCIMSG_CON_DATA: + data=PCICON_GET_REG(PCICON_RECEIVE_REG); + recbuf[w_ptr++]=(int)(data&0xff); + PCI_CON_PRINTF(" Data Console %lX, %X %d %d %X\n",data,((int)(data&0xFF)), + r_ptr,w_ptr,recbuf[w_ptr-1]); + if(w_ptr==REC_BUFFER_SIZE) + w_ptr=0; + if(w_ptr<r_ptr) + diff=r_ptr+REC_BUFFER_SIZE-w_ptr; + else + diff=r_ptr-w_ptr; + if(diff>(REC_BUFFER_SIZE-4)) + buff_full=1; + else + /* clear Mail box */ + PCICON_SET_REG(PCICON_RECEIVE_REG,0L); + break; + default: + serial_printf(" PCI9056_PCI_TO_LOC_DBELL = %08lX\n",reg); + } + /* clear IRQ */ + PCICON_SET_REG(PCICON_ACK_REG,~0L); + } + return 0; +} + +void pci_con_connect(void) +{ + unsigned long reg; + conn=0; + reg=PCICON_GET_REG(PCI9056_INT_CTRL_STAT); + /* default 0x0f010180 */ + reg &= 0xff000000; + reg |= 0x00030000; /* enable local dorbell */ + reg |= 0x00000300; /* enable PCI dorbell */ + PCICON_SET_REG(PCI9056_INT_CTRL_STAT , reg); + irq_install_handler (0x2, (interrupt_handler_t *) pci_dorbell_irq,NULL); + memset (&pci_con_dev, 0, sizeof (pci_con_dev)); + strcpy (pci_con_dev.name, "pci_con"); + pci_con_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + pci_con_dev.putc = pci_con_putc; + pci_con_dev.puts = pci_con_puts; + pci_con_dev.getc = pci_con_getc; + pci_con_dev.tstc = pci_con_tstc; + stdio_register (&pci_con_dev); + printf("PATI ready for PCI connection, type ctrl-c for exit\n"); + do { + udelay(10); + if((volatile int)conn) + break; + if(ctrlc()) { + irq_free_handler(0x2); + return; + } + }while(1); + console_assign(stdin,"pci_con"); + console_assign(stderr,"pci_con"); + console_assign(stdout,"pci_con"); +} + +void pci_con_disc(void) +{ + console_assign(stdin,"serial"); + console_assign(stderr,"serial"); + console_assign(stdout,"serial"); + PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_DISC); + /* reconnection */ + irq_free_handler(0x02); + pci_con_connect(); +} +#endif /* #ifdef CONFIG_SYS_PCI_CON_DEVICE */ + +/* + * Absolute environment address for linker file. + */ +GEN_ABS(env_start, CONFIG_ENV_OFFSET + CONFIG_SYS_FLASH_BASE); diff --git a/u-boot/board/mpl/pati/pati.h b/u-boot/board/mpl/pati/pati.h new file mode 100644 index 0000000..86c7a41 --- /dev/null +++ b/u-boot/board/mpl/pati/pati.h @@ -0,0 +1,440 @@ +/* + * (C) Copyright 2003 + * Denis Peter, d.peter@mpl.ch + * 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 + */ +/************************************************************************ + * MACROS and register definitions for PATI Registers + ************************************************************************/ +#ifndef __PATI_H_ +#define __PATI_H_ 1 + +#define PLD_PART_ID 0x0 +#define PLD_BOARD_TIMING 0x4 +#define PLD_CONF_REG1 0x8 +#define PLD_CONF_REG2 0xC +#define PLD_CONF_RES 0x10 + +#define SET_REG_BIT(y,x) (y<<(31-x)) +#define GET_REG_BIT(y,x) ((y>>(31-x)) & 0x1L) + +/* SDRAM Controller PLD_PART_ID */ +/* 9 10 11 12 13 14 19 31 */ +#define SDRAM_PART3 9 +#define SDRAM_PART2 10 +#define SDRAM_PART1 11 +#define SDRAM_PART0 12 +#define SDRAM_ID3 13 +#define SDRAM_ID2 14 +#define SDRAM_ID1 19 +#define SDRAM_ID0 31 + +#define SDRAM_PART(x) ( \ + (GET_REG_BIT(x,SDRAM_PART3)<<3) |\ + (GET_REG_BIT(x,SDRAM_PART2)<<2) |\ + (GET_REG_BIT(x,SDRAM_PART1)<<1) |\ + (GET_REG_BIT(x,SDRAM_PART0))) + +#define SDRAM_ID(x) ( \ + (GET_REG_BIT(x,SDRAM_ID3)<<3) |\ + (GET_REG_BIT(x,SDRAM_ID2)<<2) |\ + (GET_REG_BIT(x,SDRAM_ID1)<<1) |\ + (GET_REG_BIT(x,SDRAM_ID0))) + +/* System Controller */ +/* 0 1 3 4 5 16 20 28 29 30 */ +#define SYSCNTR_PART4 0 +#define SYSCNTR_PART3 1 +#define SYSCNTR_PART2 3 +#define SYSCNTR_PART1 4 +#define SYSCNTR_PART0 5 +#define SYSCNTR_ID4 16 +#define SYSCNTR_ID3 20 +#define SYSCNTR_ID2 28 +#define SYSCNTR_ID1 29 +#define SYSCNTR_ID0 30 + +#define SYSCNTR_PART(x) ( \ + (GET_REG_BIT(x,SYSCNTR_PART4)<<4) |\ + (GET_REG_BIT(x,SYSCNTR_PART3)<<3) |\ + (GET_REG_BIT(x,SYSCNTR_PART2)<<2) |\ + (GET_REG_BIT(x,SYSCNTR_PART1)<<1) |\ + (GET_REG_BIT(x,SYSCNTR_PART0))) + +#define SYSCNTR_ID(x) ( \ + (GET_REG_BIT(x,SYSCNTR_ID4)<<4) |\ + (GET_REG_BIT(x,SYSCNTR_ID3)<<3) |\ + (GET_REG_BIT(x,SYSCNTR_ID2)<<2) |\ + (GET_REG_BIT(x,SYSCNTR_ID1)<<1) |\ + (GET_REG_BIT(x,SYSCNTR_ID0))) + +/* SDRAM Controller PLD_BOARD_TIMING */ +/* 9 10 11 12 13 14 19 31 */ +#define SDRAM_CAL 9 +#define SDRAM_RCD 10 +#define SDRAM_WREQ 11 +#define SDRAM_PR 12 +#define SDRAM_RC 13 +#define SDRAM_LMR 14 +#define SDRAM_IIP 19 +#define SDRAM_RES0 31 +/* System Controller */ +/* 0 1 3 4 5 16 20 28 29 30 */ +#define SYSCNTR_BREV0 0 +#define SYSCNTR_BREV1 1 +#define SYSCNTR_BREV2 3 +#define SYSCNTR_BREV3 4 +#define SYSCNTR_RES0 5 +#define SYSCNTR_RES1 16 +#define SYSCNTR_RES2 20 +#define SYSCNTR_FLWAIT2 28 +#define SYSCNTR_FLWAIT1 29 +#define SYSCNTR_FLWAIT0 30 + +#define SYSCNTR_BREV(x) ( \ + (GET_REG_BIT(x,SYSCNTR_BREV3)<<3) |\ + (GET_REG_BIT(x,SYSCNTR_BREV2)<<2) |\ + (GET_REG_BIT(x,SYSCNTR_BREV1)<<1) |\ + (GET_REG_BIT(x,SYSCNTR_BREV0))) + +#define GET_SYSCNTR_FLWAIT(x) ( \ + (GET_REG_BIT(x,SYSCNTR_FLWAIT2)<<2) |\ + (GET_REG_BIT(x,SYSCNTR_FLWAIT1)<<1) |\ + (GET_REG_BIT(x,SYSCNTR_FLWAIT0))) + +#define SET_SYSCNTR_FLWAIT(x) ( \ + (SET_REG_BIT(((x & 0x04)!=0),SYSCNTR_FLWAIT2)) |\ + (SET_REG_BIT(((x & 0x02)!=0)x,SYSCNTR_FLWAIT1)) |\ + (SET_REG_BIT(((x & 0x01)!=0)x,SYSCNTR_FLWAIT0))) + +/* SDRAM Controller REG 2*/ +/* 9 10 11 12 13 14 19 31 */ +#define SDRAM_MUX0 9 +#define SDRAM_MUX1 10 +#define SDRAM_PDIS 11 +#define SDRAM_RES1 12 +#define SDRAM_RES2 13 +#define SDRAM_RES3 14 +#define SDRAM_RES4 19 +#define SDRAM_RIP 31 + +#define GET_SDRAM_MUX(x) ( \ + (GET_REG_BIT(x,SDRAM_MUX1)<<1)| \ + (GET_REG_BIT(x,SDRAM_MUX0))) + + +/* System Controller */ +/* 0 1 3 4 5 16 20 28 29 30 */ +#define SYSCNTR_FLAG 0 +#define SYSCNTR_IP 1 +#define SYSCNTR_BIND2 3 +#define SYSCNTR_BIND1 4 +#define SYSCNTR_BIND0 5 +#define SYSCNTR_PRM 16 +#define SYSCNTR_ICW 20 +#define SYSCNTR_ISB2 28 +#define SYSCNTR_ISB1 29 +#define SYSCNTR_ISB0 30 + +#define GET_SYSCNTR_BOOTIND(x) ( \ + (GET_REG_BIT(x,SYSCNTR_BIND2)<<2) |\ + (GET_REG_BIT(x,SYSCNTR_BIND1)<<1) |\ + (GET_REG_BIT(x,SYSCNTR_BIND0))) + +#define SET_SYSCNTR_BOOTIND(x) ( \ + (SET_REG_BIT(((x & 0x04)!=0),SYSCNTR_BIND2)) |\ + (SET_REG_BIT(((x & 0x02)!=0)x,SYSCNTR_BIND1))| \ + (SET_REG_BIT(((x & 0x01)!=0)x,SYSCNTR_BIND0))) + +#define GET_SYSCNTR_ISB(x) ( \ + (GET_REG_BIT(x,SYSCNTR_ISB2)<<2)| \ + (GET_REG_BIT(x,SYSCNTR_ISB1)<<1)| \ + (GET_REG_BIT(x,SYSCNTR_ISB0))) + +#define SET_SYSCNTR_ISB(x) ( \ + (SET_REG_BIT(((x & 0x04)!=0),SYSCNTR_ISB2))| \ + (SET_REG_BIT(((x & 0x02)!=0)x,SYSCNTR_ISB))| \ + (SET_REG_BIT(((x & 0x01)!=0)x,SYSCNTR_ISB0))) + +/* SDRAM Controller REG 3*/ +/* 9 10 11 12 13 14 19 31 */ +#define SDRAM_RES5 9 +#define SDRAM_CFG1 10 +#define SDRAM_CFG2 11 +#define SDRAM_CFG3 12 +#define SDRAM_RES6 13 +#define SDRAM_CFG5 14 +#define SDRAM_CFG6 19 +#define SDRAM_RES7 31 + +#define GET_SDRAM_CFG(x) ( \ + (GET_REG_BIT(x,SDRAM_CFG6)<<4) |\ + (GET_REG_BIT(x,SDRAM_CFG5)<<3) |\ + (GET_REG_BIT(x,SDRAM_CFG3)<<2) |\ + (GET_REG_BIT(x,SDRAM_CFG2)<<1) |\ + (GET_REG_BIT(x,SDRAM_CFG1))) + +/* System Controller */ +/* 0 1 3 4 5 16 20 28 29 30 */ +#define SYSCNTR_BDIS 0 +#define SYSCNTR_PCIM 1 +#define SYSCNTR_CFG0 3 +#define SYSCNTR_CFG1 4 +#define SYSCNTR_CFG2 5 +#define SYSCNTR_CFG3 16 +#define SYSCNTR_BOOTEN 20 +#define SYSCNTR_CPU_VPP 28 +#define SYSCNTR_FL_VPP 29 +#define SYSCNTR_FL_WP 30 + +#define GET_SYSCNTR_CFG(x) ( \ + (GET_REG_BIT(x,SYSCNTR_CFG3)<<3)| \ + (GET_REG_BIT(x,SYSCNTR_CFG2)<<2)| \ + (GET_REG_BIT(x,SYSCNTR_CFG1)<<1)| \ + (GET_REG_BIT(x,SYSCNTR_CFG0))) + + +/*************************************************************** + * MISC Defines + ***************************************************************/ + +#define PCI_VENDOR_ID_MPL 0x18E6 +#define PCI_DEVICE_ID_PATI 0x00DA + +#if defined(CONFIG_MIP405) +#define PATI_FIRMWARE_START_OFFSET 0x00300000 +#define PATI_ISO_STRING "MEV-10084-001" +#endif + +#define PATI_ENDIAN_MODE 0x3E + +/******************************************* + * PATI Mapping: + * ------------- + * PCI Map: + * ------- + * All addreses are mapped into the memory area + * (IO Area on some areas may also be possible) + * - pci_cfg_mem_base: fixed address to the PLX config area size 512Bytes + * - pci_space0_addr: configurable + * - pci_space1_addr configurable + * + * Local Map: + * ---------- + * Local addresses (Remap) + * - SDRAM 0x06000000 Size 16MByte mask 0xff000000 + * - EPLD CFG 0x07000000 Size 512Bytes + * - FLASH 0x03000000 Size up to 8MByte + * - CPU 0x01000000 Size 4MByte (only accessable if special configured) + * + * Implemention: + * ------------- + * To prevent using large resources reservation on the host following + * PCI mapping is choosed: + * - pci_cfg_mem_base: fixed address to the PLX config area size 512Bytes + * - pci_space0_addr: configured to the EPLD Config Area size 256Bytes + * - pci_space1_addr: configured to the SDRAM Area size 1MBytes, this + * space is used to switch between SDRAM, Flash and CPU + * + */ + +/* Attribute definitions */ +#define PATI_BUS_SIZE_8 0 +#define PATI_BUS_SIZE_16 1 +#define PATI_BUS_SIZE_32 3 + +#define PATI_SPACE0_MASK (0xFEFFFE00) /* Mask Attributes */ +#define PATI_SPACE1_MASK (0x00000000) /* Mask Attributes */ + +#define PATI_EXTRA_LONG_EEPROM 1 + +#define SPACE0_TA_ENABLE (1<<6) +#define SPACE1_TA_ENABLE (1<<6) + +/* Config Area */ +#define PATI_LOC_CFG_ADDR 0x07000000 /* Local Address */ +#define PATI_LOC_CFG_MASK 0xFFFFFF00 /* 256 Bytes */ +/* Attributes */ +#define PATI_LOC_CFG_BUS_SIZE PATI_BUS_SIZE_32 /* 32 Bit */ +#define PATI_LOC_CFG_BURST 0 /* No Burst */ +#define PATI_LOC_CFG_NO_PREFETCH 1 /* No Prefetch */ +#define PATI_LOC_CFG_TA_ENABLE 1 /* Enable TA */ + +#define PATI_LOC_CFG_SPACE0_ATTR ( \ + PATI_LOC_CFG_BUS_SIZE | \ + (PATI_LOC_CFG_TA_ENABLE << 6) | \ + (PATI_LOC_CFG_NO_PREFETCH << 8) | \ + (PATI_LOC_CFG_BURST << 24) | \ + (PATI_EXTRA_LONG_EEPROM << 25)) + +/* should never be used */ +#define PATI_LOC_CFG_SPACE1_ATTR ( \ + PATI_LOC_CFG_BUS_SIZE | \ + (PATI_LOC_CFG_TA_ENABLE << 6) | \ + (PATI_LOC_CFG_NO_PREFETCH << 9) | \ + (PATI_LOC_CFG_BURST << 8)) + + +/* SDRAM Area */ +#define PATI_LOC_SDRAM_ADDR 0x06000000 /* Local Address */ +#define PATI_LOC_SDRAM_MASK 0xFFF00000 /* 1MByte */ +/* Attributes */ +#define PATI_LOC_SDRAM_BUS_SIZE PATI_BUS_SIZE_32 /* 32 Bit */ +#define PATI_LOC_SDRAM_BURST 0 /* No Burst */ +#define PATI_LOC_SDRAM_NO_PREFETCH 0 /* Prefetch */ +#define PATI_LOC_SDRAM_TA_ENABLE 1 /* Enable TA */ + +/* should never be used */ +#define PATI_LOC_SDRAM_SPACE0_ATTR ( \ + PATI_LOC_SDRAM_BUS_SIZE | \ + (PATI_LOC_SDRAM_TA_ENABLE << 6) | \ + (PATI_LOC_SDRAM_NO_PREFETCH << 8) | \ + (PATI_LOC_SDRAM_BURST << 24) | \ + (PATI_EXTRA_LONG_EEPROM << 25)) + +#define PATI_LOC_SDRAM_SPACE1_ATTR ( \ + PATI_LOC_SDRAM_BUS_SIZE | \ + (PATI_LOC_SDRAM_TA_ENABLE << 6) | \ + (PATI_LOC_SDRAM_NO_PREFETCH << 9) | \ + (PATI_LOC_SDRAM_BURST << 8)) + + +/* Flash Area */ +#define PATI_LOC_FLASH_ADDR 0x03000000 /* Local Address */ +#define PATI_LOC_FLASH_MASK 0xFFF00000 /* 1MByte */ +/* Attributes */ +#define PATI_LOC_FLASH_BUS_SIZE PATI_BUS_SIZE_16 /* 16 Bit */ +#define PATI_LOC_FLASH_BURST 0 /* No Burst */ +#define PATI_LOC_FLASH_NO_PREFETCH 1 /* No Prefetch */ +#define PATI_LOC_FLASH_TA_ENABLE 1 /* Enable TA */ + +/* should never be used */ +#define PATI_LOC_FLASH_SPACE0_ATTR ( \ + PATI_LOC_FLASH_BUS_SIZE | \ + (PATI_LOC_FLASH_TA_ENABLE << 6) | \ + (PATI_LOC_FLASH_NO_PREFETCH << 8) | \ + (PATI_LOC_FLASH_BURST << 24) | \ + (PATI_EXTRA_LONG_EEPROM << 25)) + +#define PATI_LOC_FLASH_SPACE1_ATTR ( \ + PATI_LOC_FLASH_BUS_SIZE | \ + (PATI_LOC_FLASH_TA_ENABLE << 6) | \ + (PATI_LOC_FLASH_NO_PREFETCH << 9) | \ + (PATI_LOC_FLASH_BURST << 8)) + + +/* CPU Area */ +#define PATI_LOC_CPU_ADDR 0x01000000 /* Local Address */ +#define PATI_LOC_CPU_MASK 0xFFF00000 /* 1Mbyte */ +/* Attributes */ +#define PATI_LOC_CPU_BUS_SIZE PATI_BUS_SIZE_32 /* 32 Bit */ +#define PATI_LOC_CPU_BURST 0 /* No Burst */ +#define PATI_LOC_CPU_NO_PREFETCH 1 /* No Prefetch */ +#define PATI_LOC_CPU_TA_ENABLE 1 /* Enable TA */ + +/* should never be used */ +#define PATI_LOC_CPU_SPACE0_ATTR ( \ + PATI_LOC_CPU_BUS_SIZE | \ + (PATI_LOC_CPU_TA_ENABLE << 6) | \ + (PATI_LOC_CPU_NO_PREFETCH << 8) | \ + (PATI_LOC_CPU_BURST << 24) | \ + (PATI_EXTRA_CPU_EEPROM << 25)) + +#define PATI_LOC_CPU_SPACE1_ATTR ( \ + PATI_LOC_CPU_BUS_SIZE | \ + (PATI_LOC_CPU_TA_ENABLE << 6) | \ + (PATI_LOC_CPU_NO_PREFETCH << 9) | \ + (PATI_LOC_CPU_BURST << 8)) + +/*************************************************** + * Hardware Config word definition + ***************************************************/ +#define BOOT_EXT_FLASH 0x00000000 +#define BOOT_INT_FLASH 0x00000004 +#define BOOT_FROM_PCI 0x00000006 +#define BOOT_FROM_SDRAM 0x00000005 + +#define ENABLE_INT_ARB 0x00000008 + +#define INITIAL_IRQ_PREF 0x00000010 + +#define INITIAL_MEM_0M 0x00000000 +#define INITIAL_MEM_4M 0x00000080 +#define INITIAL_MEM_8M 0x00000040 +#define INITIAL_MEM_12M 0x000000C0 +#define INITIAL_MEM_16M 0x00000020 +#define INITIAL_MEM_20M 0x000000A0 +#define INITIAL_MEM_24M 0x00000060 +#define INITIAL_MEM_28M 0x000000E0 +/* CONF */ +#define INTERNAL_HWCONF 0x00000100 +/* PRPM */ +#define LOCAL_CPU_SLAVE 0x00000200 +/* BDIS */ +#define DISABLE_MEM_CNTR 0x00000400 +/* PCIM */ +#define PCI_MASTER_ONLY 0x00000800 + + +#define PATI_HW_START ((BOOT_EXT_FLASH | INITIAL_MEM_28M | INITIAL_IRQ_PREF)) +#define PATI_HW_PCI_ONLY ((BOOT_EXT_FLASH | INITIAL_MEM_28M | INITIAL_IRQ_PREF | PCI_MASTER_ONLY)) +#define PATI_HW_CPU_ACC ((BOOT_EXT_FLASH | INITIAL_MEM_12M | INITIAL_IRQ_PREF | PCI_MASTER_ONLY)) +#define PATI_HW_CPU_SLAVE ((BOOT_EXT_FLASH | INITIAL_MEM_12M | INITIAL_IRQ_PREF | PCI_MASTER_ONLY | LOCAL_CPU_SLAVE)) + +/*************************************************** + * Direct Master Config + ***************************************************/ +#define PATI_DMASTER_PCI_ADDR 0x01000000 +#define PATI_BUS_MASTER 1 + + +#define PATI_DMASTER_MASK 0xFFF00000 /* 1MByte */ +#define PATI_DMASTER_ADDR 0x01000000 /* Local Address */ + +#define PATI_DMASTER_MEMORY_EN 0x00000001 /* 0x00000001 */ +#define PATI_DMASTER_READ_AHEAD 0x00000004 /* 0x00000004 */ +#define PATI_DMASTER_READ_NOT_AHEAD 0x00000000 /* 0x00000004 */ +#define PATI_DMASTER_PRE_SIZE_CNTRL_0 0x00000000 +#define PATI_DMASTER_PRE_SIZE_CNTRL_4 0x00000008 +#define PATI_DMASTER_PRE_SIZE_CNTRL_8 0x00001000 +#define PATI_DMASTER_PRE_SIZE_CNTRL_16 0x00001008 +#define PATI_DMASTER_REL_PCI 0x00000000 +#define PATI_DMASTER_NOT_REL_PCI 0x00000010 +#define PATI_DMASTER_WR_INVAL 0x00000200 +#define PATI_DMASTER_NOT_WR_INVAL 0x00000000 +#define PATI_DMASTER_PRE_LIMIT 0x00000800 +#define PATI_DMASTER_PRE_CONT 0x00000000 +#define PATI_DMASTER_DELAY_WR_0 0x00000000 +#define PATI_DMASTER_DELAY_WR_4 0x00004000 +#define PATI_DMASTER_DELAY_WR_8 0x00008000 +#define PATI_DMASTER_DELAY_WR_16 0x0000C000 + +#define PATI_DMASTER_PCI_ADDR_MASK 0xFFFF0000 + +#define PATI_DMASTER_ATTR \ + PATI_DMASTER_MEMORY_EN | \ + PATI_DMASTER_READ_AHEAD | \ + PATI_DMASTER_PRE_SIZE_CNTRL_4 | \ + PATI_DMASTER_REL_PCI | \ + PATI_DMASTER_NOT_WR_INVAL | \ + PATI_DMASTER_PRE_LIMIT | \ + PATI_DMASTER_DELAY_WR_0 + + +#endif /* #ifndef __PATI_H_ */ diff --git a/u-boot/board/mpl/pati/pci_eeprom.h b/u-boot/board/mpl/pati/pci_eeprom.h new file mode 100644 index 0000000..af34b86 --- /dev/null +++ b/u-boot/board/mpl/pati/pci_eeprom.h @@ -0,0 +1,91 @@ + +#ifndef __PCI_EEPROM_H_ +#define __PCI_EEPROM_H_ 1 + +#include "pati.h" +/****************************************************************************** + * Eeprom Support + ******************************************************************************/ +/********************************************** +* Definitions +**********************************************/ +#define EE46_CMD_LEN 9 /* Bits in instructions */ +#define EE56_CMD_LEN 11 /* Bits in instructions */ +#define EE66_CMD_LEN 11 /* Bits in instructions */ +#define EE_READ 0x0180 /* 01 1000 0000 read instruction */ +#define EE_WRITE 0x0140 /* 01 0100 0000 write instruction */ +#define EE_WREN 0x0130 /* 01 0011 0000 write enable instruction */ +#define EE_WRALL 0x0110 /* 01 0001 0000 write all registers */ +#define EE_PRREAD 0x0180 /* 01 1000 0000 read address stored in Protect Register */ +#define EE_PRWRITE 0x0140 /* 01 0100 0000 write the address into PR */ +#define EE_WDS 0x0100 /* 01 0000 0000 write disable instruction */ +#define EE_PREN 0x0130 /* 01 0011 0000 protect enable instruction */ +#define EE_PRCLEAR 0x01FF /* 01 1111 1111 clear protect register instr */ +#define EE_PRDS 0x0100 /* 01 0000 0000 ONE TIME ONLY, permenant */ + +/*************************************************** + * EEPROM + ***************************************************/ +#define LOW_WORD(x) (((x) & 0xFFFF)) +#define HIGH_WORD(x) (((x) >> 16) & 0xFFFF) + +typedef struct pci_eeprom_t { + unsigned short offset; + unsigned short value; +} pci_eeprom; + +static pci_eeprom pati_eeprom[] = { + { 0x00,PCI_DEVICE_ID_PATI }, /* PCI Device ID PCIIDR[31:16] */ + { 0x02,PCI_VENDOR_ID_MPL }, /* PCI Vendor ID PCIIDR[15:0] */ + { 0x04,PCI_CLASS_PROCESSOR_POWERPC }, /* PCI Class Code PCICCR[23:8] */ + { 0x06,0x00BA }, /* PCI Class Code / PCI Revision ID PCICCR[7:0] / PCIREV[7:0] */ + { 0x08,0x0007 }, /* PCI Maximum Latency / PCI Minimum Grant PCIMLR[7:0] / PCIMGR[7:0] */ + { 0x0A,0x0100 }, /* PCI Interrupt Pin / PCI Interrupt Line PCIIPR[7:0] / PCIILR[7:0] */ + { 0x0C,0x0000 }, /* MSW of Mailbox 0 (User Defined) PCI9056_MAILBOX0[31:16] */ + { 0x0E,0x0000 }, /* LSW of Mailbox 0 (User Defined) PCI9056_MAILBOX0[15:0] */ + { 0x10,0x0000 }, /* MSW of Mailbox 1 (User Defined) PCI9056_MAILBOX1[31:16] */ + { 0x12,0x0000 }, /* LSW of Mailbox 1 (User Defined) PCI9056_MAILBOX1[15:0] */ + { 0x14,HIGH_WORD(PATI_LOC_CFG_MASK) }, /* MSW of Direct Slave Local Address Space 0 Range LAS0RR[31:16] */ + { 0x16,LOW_WORD(PATI_LOC_CFG_MASK) }, /* LSW of Direct Slave Local Address Space 0 Range LAS0RR[15:0] */ + { 0x18,HIGH_WORD(PATI_LOC_CFG_ADDR) }, /* MSW of Direct Slave Local Address Space 0 Local Base Address (Remap) LAS0BA[31:16] (CFG) */ + { 0x1A,LOW_WORD(PATI_LOC_CFG_ADDR)|1 }, /* LSW of Direct Slave Local Address Space 0 Local Base Address (Remap) LAS0BA[15:2, 0], Reserved [1] */ + { 0x1C,0x0000 }, /* MSW of Mode/DMA Arbitration MARBR[31, 29:16] or DMAARB[31, 29:16], Reserved [30] */ + { 0x1E,0x0000 }, /* LSW of Mode/DMA Arbitration MARBR[15:0] or DMAARB[15:0] */ + { 0x20,0x0030 }, /* Local Miscellaneous Control 2 / Serial EEPROM WP Addr Boundary LMISC2[5:0], Res[7:6] / PROT_AREA[6:0], Res[7] */ + { 0x22,0x0510 }, /* Local Miscellaneous Control 1 / Local Bus Big/Little Endian Descriptor LMISC1[7:0] / BIGEND[7:0] */ + { 0x24,0x0000 }, /* MSW of Direct Slave Expansion ROM Range EROMRR[31:16] */ + { 0x26,0x0000 }, /* LSW of Direct Slave Expansion ROM Range EROMRR[15:11, 0], Reserved [10:1] */ + { 0x28,0x0000 }, /* MSW of Direct Slave Expansion ROM Local Base Address (Remap) and BREQo Control EROMBA[31:16] */ + { 0x2A,0x0000 }, /* LSW of Direct Slave Expansion ROM Local Base Address (Remap) and BREQo Control EROMBA[15:11, 5:0], Reserved [10:6] */ + { 0x2C,(0x4243 | HIGH_WORD((PATI_LOC_CFG_SPACE0_ATTR))) }, /* MSW of Local Address Space 0/Expansion ROM Bus Region Descriptor LBRD0[31:16] */ + { 0x2E,LOW_WORD(PATI_LOC_CFG_SPACE0_ATTR) }, /* LSW of Local Address Space 0/Expansion ROM Bus Region Descriptor LBRD0[15:0] */ + { 0x30,HIGH_WORD(PATI_DMASTER_MASK) }, /* MSW of Local Range for Direct Master-to-PCI DMRR[31:16] */ + { 0x32,LOW_WORD(PATI_DMASTER_MASK) }, /* LSW of Local Range for Direct Master-to-PCI (Reserved) DMRR[15:0] */ + { 0x34,HIGH_WORD(PATI_DMASTER_ADDR) }, /* MSW of Local Base Address for Direct Master-to-PCI Memory DMLBAM[31:16] */ + { 0x36,LOW_WORD(PATI_DMASTER_ADDR) }, /* LSW of Local Base Address for Direct Master-to-PCI Memory (Reserved) DMLBAM[15:0] */ + { 0x38,0x0000 }, /* MSW of Local Bus Address for Direct Master-to-PCI I/O Configuration DMLBAI[31:16] */ + { 0x3A,0x0000 }, /* LSW of Local Bus Address for Direct Master-to-PCI I/O Configuration (Reserved) DMLBAI[15:0] */ + { 0x3C,0x0000 }, /* MSW of PCI Base Address (Remap) for Direct Master-to-PCI Memory DMPBAM[31:16] */ + { 0x3E,0x0000 }, /* LSW of PCI Base Address (Remap) for Direct Master-to-PCI Memory DMPBAM[15:0] */ + { 0x40,0x0000 }, /* MSW of PCI Configuration Address for Direct Master-to-PCI I/O Configuration DMCFGA[31, 23:16] Reserved [30:24]*/ + { 0x42,0x0000 }, /* LSW of PCI Configuration Address for Direct Master-to-PCI I/O Configuration DMCFGA[15:0] */ + { 0x44,0x0000 }, /* PCI Subsystem ID PCISID[15:0] */ + { 0x46,0x0000 }, /* PCI Subsystem Vendor ID PCISVID[15:0] */ + { 0x48,HIGH_WORD(PATI_LOC_SDRAM_MASK) }, /* MSW of Direct Slave Local Address Space 1 Range (1 MB) LAS1RR[31:16] */ + { 0x4A,LOW_WORD(PATI_LOC_SDRAM_MASK) }, /* LSW of Direct Slave Local Address Space 1 Range (1 MB) LAS1RR[15:0] */ + { 0x4C,HIGH_WORD(PATI_LOC_SDRAM_ADDR) }, /* MSW of Direct Slave Local Address Space 1 Local Base Address (Remap) LAS1BA[31:16] (SDRAM) */ + { 0x4E,LOW_WORD(PATI_LOC_SDRAM_ADDR) | 0x1 }, /* LSW of Direct Slave Local Address Space 1 Local Base Address (Remap) LAS1BA[15:2, 0], Reserved [1] */ + { 0x50,HIGH_WORD(PATI_LOC_SDRAM_SPACE1_ATTR) }, /* MSW of Local Address Space 1 Bus Region Descriptor LBRD1[31:16] */ + { 0x52,LOW_WORD(PATI_LOC_SDRAM_SPACE1_ATTR) }, /* LSW of Local Address Space 1 Bus Region Descriptor (Reserved) LBRD1[15:0] */ + { 0x54,0x0000 }, /* Hot Swap Control/Status (Reserved) Reserved */ + { 0x56,0x0000 }, /* Hot Swap Next Capability Pointer / Hot Swap Control HS_NEXT[7:0] / HS_CNTL[7:0] */ + { 0x58,0x0000 }, /* Reserved Reserved */ + { 0x5A,0x0000 }, /* PCI Arbiter Control PCIARB[3:0], Reserved [15:4] */ + { 0x5C,0x0000 }, /* Power Management Capabilities PMC[15:9, 2:0] */ + { 0x5E,0x0000 }, /* Power Management Next Capability Pointer (Reserved) / Power Management Capability ID (Reserved) Reserved*/ + { 0x60,0x0000 }, /* Power Management Data / PMCSR Bridge Support Extension (Reserved) PMDATA[7:0] / Reserved */ + { 0x62,0x0000 }, /* Power Management Control/Status PMCSR[14:8] */ + { 0xFFFF,0xFFFF} /* terminaror */ +}; +#define PATI_EEPROM_LAST_OFFSET 0x64 +#endif /* #ifndef __PCI_EEPROM_H_ */ diff --git a/u-boot/board/mpl/pati/plx9056.h b/u-boot/board/mpl/pati/plx9056.h new file mode 100644 index 0000000..cd4df18 --- /dev/null +++ b/u-boot/board/mpl/pati/plx9056.h @@ -0,0 +1,111 @@ +/* + * (C) Copyright 2003 + * Denis Peter, d.peter@mpl.ch + * 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 + */ +/* PLX9096 register definitions +*/ +#ifndef __PLX9056_H_ +#define __PLX9056_H_ 1 + +#include <pci.h> + +#ifdef PLX9056_LOC +#define LOCAL_OFFSET 0x080 +/* PCI Config regs */ +#else +#define LOCAL_OFFSET 0x000 +#endif + +#define PCI9056_VENDOR_ID PCI_VENDOR_ID +/*#define PCI9656_DEVICE_ID PCI_DEVICE_ID */ +#define PCI9056_COMMAND PCI_COMMAND +/*#define PCI9656_STATUS PCI_STATUS */ +#define PCI9056_REVISION PCI_REVISION_ID + +#define PCI9056_CACHE_SIZE PCI_CACHE_LINE_SIZE +#define PCI9056_RTR_BASE PCI_BASE_ADDRESS_0 +#define PCI9056_RTR_IO_BASE PCI_BASE_ADDRESS_1 +#define PCI9056_LOCAL_BASE0 PCI_BASE_ADDRESS_2 +#define PCI9056_LOCAL_BASE1 PCI_BASE_ADDRESS_3 +#define PCI9056_UNUSED_BASE1 PCI_BASE_ADDRESS_4 +#define PCI9056_UNUSED_BASE2 PCI_BASE_ADDRESS_5 +#define PCI9056_CIS_PTR PCI_CARDBUS_CIS +#define PCI9056_SUB_ID PCI_SUBSYSTEM_VENDOR_ID +#define PCI9056_EXP_ROM_BASE PCI_ROM_ADDRESS +#define PCI9056_CAP_PTR PCI_CAPABILITY_LIST +#define PCI9056_INT_LINE PCI_INTERRUPT_LINE + +#if defined(PLX9056_LOC) + #define PCI9056_PM_CAP_ID 0x180 + #define PCI9056_PM_CSR 0x184 + #define PCI9056_HS_CAP_ID 0x188 + #define PCI9056_VPD_CAP_ID 0x18C + #define PCI9056_VPD_DATA 0x190 +#endif + + +#define PCI_DEVICE_ID_PLX9056 0x9056 + +/* Local Configuration Registers Accessible via the PCI Base address + Variable */ +#define PCI9056_SPACE0_RANGE (0x000 + LOCAL_OFFSET) +#define PCI9056_SPACE0_REMAP (0x004 + LOCAL_OFFSET) +#define PCI9056_LOCAL_DMA_ARBIT (0x008 + LOCAL_OFFSET) +#define PCI9056_ENDIAN_DESC (0x00c + LOCAL_OFFSET) +#define PCI9056_EXP_ROM_RANGE (0x010 + LOCAL_OFFSET) +#define PCI9056_EXP_ROM_REMAP (0x014 + LOCAL_OFFSET) +#define PCI9056_SPACE0_ROM_DESC (0x018 + LOCAL_OFFSET) +#define PCI9056_DM_RANGE (0x01c + LOCAL_OFFSET) +#define PCI9056_DM_MEM_BASE (0x020 + LOCAL_OFFSET) +#define PCI9056_DM_IO_BASE (0x024 + LOCAL_OFFSET) +#define PCI9056_DM_PCI_MEM_REMAP (0x028 + LOCAL_OFFSET) +#define PCI9056_DM_PCI_IO_CONFIG (0x02c + LOCAL_OFFSET) +#define PCI9056_SPACE1_RANGE (0x0f0 + LOCAL_OFFSET) +#define PCI9056_SPACE1_REMAP (0x0f4 + LOCAL_OFFSET) +#define PCI9056_SPACE1_DESC (0x0f8 + LOCAL_OFFSET) +#define PCI9056_DM_DAC (0x0fc + LOCAL_OFFSET) + +#ifdef PLX9056_LOC +#define PCI9056_ARBITER_CTRL 0x1A0 +#define PCI9056_ABORT_ADDRESS 0x1A4 +#endif + +/* Runtime registers PCI Address + LOCAL_OFFSET */ +#ifdef PLX9056_LOC +#define PCI9056_MAILBOX0 0x0C0 +#define PCI9056_MAILBOX1 0x0C4 +#else +#define PCI9056_MAILBOX0 0x078 +#define PCI9056_MAILBOX1 0x07c +#endif + +#define PCI9056_MAILBOX2 (0x048 + LOCAL_OFFSET) +#define PCI9056_MAILBOX3 (0x04c + LOCAL_OFFSET) +#define PCI9056_MAILBOX4 (0x050 + LOCAL_OFFSET) +#define PCI9056_MAILBOX5 (0x054 + LOCAL_OFFSET) +#define PCI9056_MAILBOX6 (0x058 + LOCAL_OFFSET) +#define PCI9056_MAILBOX7 (0x05c + LOCAL_OFFSET) +#define PCI9056_PCI_TO_LOC_DBELL (0x060 + LOCAL_OFFSET) +#define PCI9056_LOC_TO_PCI_DBELL (0x064 + LOCAL_OFFSET) +#define PCI9056_INT_CTRL_STAT (0x068 + LOCAL_OFFSET) +#define PCI9056_EEPROM_CTRL_STAT (0x06c + LOCAL_OFFSET) +#define PCI9056_PERM_VENDOR_ID (0x070 + LOCAL_OFFSET) +#define PCI9056_REVISION_ID (0x074 + LOCAL_OFFSET) + +#endif /* #ifndef __PLX9056_H_ */ diff --git a/u-boot/board/mpl/pip405/Makefile b/u-boot/board/mpl/pip405/Makefile new file mode 100644 index 0000000..8b4bbc5 --- /dev/null +++ b/u-boot/board/mpl/pip405/Makefile @@ -0,0 +1,59 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)../common) +endif + +LIB = $(obj)lib$(BOARD).o + +COBJS = $(BOARD).o \ + ../common/flash.o cmd_pip405.o ../common/pci.o \ + ../common/isa.o ../common/kbd.o \ + ../common/usb_uhci.o \ + ../common/common_util.o + +SOBJS = init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(OBJS) $(SOBJS) + $(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/board/mpl/pip405/cmd_pip405.c b/u-boot/board/mpl/pip405/cmd_pip405.c new file mode 100644 index 0000000..554c8d1 --- /dev/null +++ b/u-boot/board/mpl/pip405/cmd_pip405.c @@ -0,0 +1,69 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 PIP405 + */ + +#include <common.h> +#include <command.h> +#include "pip405.h" +#include "../common/common_util.h" + + +extern void print_pip405_info(void); +extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + + +/* ------------------------------------------------------------------------- */ + +int do_pip405(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + + ulong led_on,led_nr; + + if (strcmp(argv[1], "info") == 0) + { + print_pip405_info(); + return 0; + } + if (strcmp(argv[1], "led") == 0) + { + led_nr = (ulong)simple_strtoul(argv[2], NULL, 10); + led_on = (ulong)simple_strtoul(argv[3], NULL, 10); + if(!led_nr) + user_led0(led_on); + else + user_led1(led_on); + return 0; + } + + return (do_mplcommon(cmdtp, flag, argc, argv)); +} +U_BOOT_CMD( + pip405, 6, 1, do_pip405, + "PIP405 specific Cmds", + "flash mem [SrcAddr] - updates U-Boot with image in memory\n" + "pip405 flash floppy [SrcAddr] - updates U-Boot with image from floppy\n" + "pip405 flash mps - updates U-Boot with image from MPS" +); + +/* ------------------------------------------------------------------------- */ diff --git a/u-boot/board/mpl/pip405/init.S b/u-boot/board/mpl/pip405/init.S new file mode 100644 index 0000000..b77517f --- /dev/null +++ b/u-boot/board/mpl/pip405/init.S @@ -0,0 +1,218 @@ +/*------------------------------------------------------------------------------+ + * This source code is dual-licensed. You may use it under the terms of + * the GNU General Public License version 2, or under the license below. + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + *-------------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Function: ext_bus_cntlr_init + * Description: Initializes the External Bus Controller for the external + * peripherals. IMPORTANT: For pass1 this code must run from + * cache since you can not reliably change a peripheral banks + * timing register (pbxap) while running code from that bank. + * For ex., since we are running from ROM on bank 0, we can NOT + * execute the code that modifies bank 0 timings from ROM, so + * we run it from cache. + * Bank 0 - Flash or Multi Purpose Socket + * Bank 1 - Multi Purpose Socket or Flash + * Bank 2 - not used + * Bank 3 - not used + * Bank 4 - not used + * Bank 5 - not used + * Bank 6 - used to switch on the 12V for the Multipurpose socket + * Bank 7 - Config Register + *-----------------------------------------------------------------------------*/ +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <configs/PIP405.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> +#include <asm/ppc4xx.h> +#include "pip405.h" + + .globl ext_bus_cntlr_init + ext_bus_cntlr_init: + mflr r4 /* save link register */ + mfdcr r3,CPC0_PSR /* get strapping reg */ + andi. r0, r3, PSR_ROM_LOC /* mask out irrelevant bits */ + bnelr /* jump back if PCI boot */ + + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + mtlr r4 /* restore link register */ + addi r4,0,14 /* set ctr to 14; used to prefetch */ + mtctr r4 /* 14 cache lines to fit this function */ + /* in cache (gives us 8x14=112 instrctns) */ +..ebcloop: + icbt r0,r3 /* prefetch cache line for addr in r3 */ + addi r3,r3,32 /* move to next cache line */ + bdnz ..ebcloop /* continue for 14 cache lines */ + + /*------------------------------------------------------------------- + * Delay to ensure all accesses to ROM are complete before changing + * bank 0 timings. + *------------------------------------------------------------------- */ + addis r3,0,0x0 + ori r3,r3,0xA000 + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + + /*----------------------------------------------------------------------- + * decide boot up mode + *----------------------------------------------------------------------- */ + addi r4,0,PB0CR + mtdcr EBC0_CFGADDR,r4 + mfdcr r4,EBC0_CFGDATA + + andi. r0, r4, 0x2000 /* mask out irrelevant bits */ + beq 0f /* jump if 8 bit bus width */ + + /* setup 16 bit things + *----------------------------------------------------------------------- + * Memory Bank 0 (16 Bit Flash) initialization + *---------------------------------------------------------------------- */ + + addi r4,0,PB1AP + mtdcr EBC0_CFGADDR,r4 + addis r4,0,(FLASH_AP_B)@h + ori r4,r4,(FLASH_AP_B)@l + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB0CR + mtdcr EBC0_CFGADDR,r4 + /* BS=0x010(4MB),BU=0x3(R/W), */ + addis r4,0,(FLASH_CR_B)@h + ori r4,r4,(FLASH_CR_B)@l + mtdcr EBC0_CFGDATA,r4 + b 1f + +0: + /* 8Bit boot mode: */ + /*----------------------------------------------------------------------- + * Memory Bank 0 Multi Purpose Socket initialization + *----------------------------------------------------------------------- */ + /* 0x7F8FFE80 slowest boot */ + addi r4,0,PB1AP + mtdcr EBC0_CFGADDR,r4 + addis r4,0,(MPS_AP_B)@h + ori r4,r4,(MPS_AP_B)@l + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB0CR + mtdcr EBC0_CFGADDR,r4 + /* BS=0x010(4MB),BU=0x3(R/W), */ + addis r4,0,(MPS_CR_B)@h + ori r4,r4,(MPS_CR_B)@l + mtdcr EBC0_CFGDATA,r4 + + +1: + /*----------------------------------------------------------------------- + * Memory Bank 2-3-4-5-6 (not used) initialization + *-----------------------------------------------------------------------*/ + addi r4,0,PB1CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB2CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB3CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB4CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB5CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB6CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + + addi r4,0,PB7CR + mtdcr EBC0_CFGADDR,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr EBC0_CFGDATA,r4 + nop /* pass2 DCR errata #8 */ + blr + +#if defined(CONFIG_BOOT_PCI) + .section .bootpg,"ax" + .globl _start_pci +/******************************************* + */ + +_start_pci: + /* first handle errata #68 / PCI_18 */ + iccci r0, r0 /* invalidate I-cache */ + lis r31, 0 + mticcr r31 /* ICCR = 0 (all uncachable) */ + isync + + mfccr0 r28 /* set CCR0[24] = 1 */ + ori r28, r28, 0x0080 + mtccr0 r28 + + /* setup PMM0MA (0xEF400004) and PMM0PCIHA (0xEF40000C) */ + lis r28, 0xEF40 + addi r28, r28, 0x0004 + stw r31, 0x0C(r28) /* clear PMM0PCIHA */ + lis r29, 0xFFF8 /* open 512 kByte */ + addi r29, r29, 0x0001/* and enable this region */ + stwbrx r29, r0, r28 /* write PMM0MA */ + + lis r28, 0xEEC0 /* address of PCIC0_CFGADDR */ + addi r29, r28, 4 /* add 4 to r29 -> PCIC0_CFGDATA */ + + lis r31, 0x8000 /* set en bit bus 0 */ + ori r31, r31, 0x304C/* device 6 func 0 reg 4C (XBCS register) */ + stwbrx r31, r0, r28 /* write it */ + + lwbrx r31, r0, r29 /* load XBCS register */ + oris r31, r31, 0x02C4/* clear BIOSCS WPE, set lower, extended and 1M extended BIOS enable */ + stwbrx r31, r0, r29 /* write back XBCS register */ + + nop + nop + b _start /* normal start */ +#endif diff --git a/u-boot/board/mpl/pip405/pip405.c b/u-boot/board/mpl/pip405/pip405.c new file mode 100644 index 0000000..7b48c06 --- /dev/null +++ b/u-boot/board/mpl/pip405/pip405.c @@ -0,0 +1,955 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * + * TODO: clean-up + */ + +#include <common.h> +#include "pip405.h" +#include <asm/processor.h> +#include <i2c.h> +#include <stdio_dev.h> +#include "../common/isa.h" +#include "../common/common_util.h" + +DECLARE_GLOBAL_DATA_PTR; + +#undef SDRAM_DEBUG + +#define FALSE 0 +#define TRUE 1 + +/* stdlib.h causes some compatibility problems; should fixe these! -- wd */ +#ifndef __ldiv_t_defined +typedef struct { + long int quot; /* Quotient */ + long int rem; /* Remainder */ +} ldiv_t; +extern ldiv_t ldiv (long int __numer, long int __denom); + +# define __ldiv_t_defined 1 +#endif + + +typedef enum { + SDRAM_NO_ERR, + SDRAM_SPD_COMM_ERR, + SDRAM_SPD_CHKSUM_ERR, + SDRAM_UNSUPPORTED_ERR, + SDRAM_UNKNOWN_ERR +} SDRAM_ERR; + +typedef struct { + const unsigned char mode; + const unsigned char row; + const unsigned char col; + const unsigned char bank; +} SDRAM_SETUP; + +static const SDRAM_SETUP sdram_setup_table[] = { + {1, 11, 9, 2}, + {1, 11, 10, 2}, + {2, 12, 9, 4}, + {2, 12, 10, 4}, + {3, 13, 9, 4}, + {3, 13, 10, 4}, + {3, 13, 11, 4}, + {4, 12, 8, 2}, + {4, 12, 8, 4}, + {5, 11, 8, 2}, + {5, 11, 8, 4}, + {6, 13, 8, 2}, + {6, 13, 8, 4}, + {7, 13, 9, 2}, + {7, 13, 10, 2}, + {0, 0, 0, 0} +}; + +static const unsigned char cal_indextable[] = { + 9, 23, 25 +}; + + +/* + * translate ns.ns/10 coding of SPD timing values + * into 10 ps unit values + */ + +unsigned short NS10to10PS (unsigned char spd_byte, unsigned char spd_version) +{ + unsigned short ns, ns10; + + /* isolate upper nibble */ + ns = (spd_byte >> 4) & 0x0F; + /* isolate lower nibble */ + ns10 = (spd_byte & 0x0F); + + return (ns * 100 + ns10 * 10); +} + +/* + * translate ns.ns/4 coding of SPD timing values + * into 10 ps unit values + */ + +unsigned short NS4to10PS (unsigned char spd_byte, unsigned char spd_version) +{ + unsigned short ns, ns4; + + /* isolate upper 6 bits */ + ns = (spd_byte >> 2) & 0x3F; + /* isloate lower 2 bits */ + ns4 = (spd_byte & 0x03); + + return (ns * 100 + ns4 * 25); +} + +/* + * translate ns coding of SPD timing values + * into 10 ps unit values + */ + +unsigned short NSto10PS (unsigned char spd_byte) +{ + return (spd_byte * 100); +} + +void SDRAM_err (const char *s) +{ +#ifndef SDRAM_DEBUG + (void) get_clocks (); + gd->baudrate = 9600; + serial_init (); +#endif + serial_puts ("\n"); + serial_puts (s); + serial_puts ("\n enable SDRAM_DEBUG for more info\n"); + for (;;); +} + + +#ifdef SDRAM_DEBUG + +void write_hex (unsigned char i) +{ + char cc; + + cc = i >> 4; + cc &= 0xf; + if (cc > 9) + serial_putc (cc + 55); + else + serial_putc (cc + 48); + cc = i & 0xf; + if (cc > 9) + serial_putc (cc + 55); + else + serial_putc (cc + 48); +} + +void write_4hex (unsigned long val) +{ + write_hex ((unsigned char) (val >> 24)); + write_hex ((unsigned char) (val >> 16)); + write_hex ((unsigned char) (val >> 8)); + write_hex ((unsigned char) val); +} + +#endif + +int board_early_init_f (void) +{ + unsigned char dataout[1]; + unsigned char datain[128]; + unsigned long sdram_size = 0; + SDRAM_SETUP *t = (SDRAM_SETUP *) sdram_setup_table; + unsigned long memclk; + unsigned long tmemclk = 0; + unsigned long tmp, bank, baseaddr, bank_size; + unsigned short i; + unsigned char rows, cols, banks, sdram_banks, density; + unsigned char supported_cal, trp_clocks, trcd_clocks, tras_clocks, + trc_clocks, tctp_clocks; + unsigned char cal_index, cal_val, spd_version, spd_chksum; + unsigned char buf[8]; + /* set up the config port */ + mtdcr (EBC0_CFGADDR, PB7AP); + mtdcr (EBC0_CFGDATA, CONFIG_PORT_AP); + mtdcr (EBC0_CFGADDR, PB7CR); + mtdcr (EBC0_CFGDATA, CONFIG_PORT_CR); + + memclk = get_bus_freq (tmemclk); + tmemclk = 1000000000 / (memclk / 100); /* in 10 ps units */ + +#ifdef SDRAM_DEBUG + (void) get_clocks (); + gd->baudrate = 9600; + serial_init (); + serial_puts ("\nstart SDRAM Setup\n"); +#endif + + /* Read Serial Presence Detect Information */ + i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + dataout[0] = 0; + for (i = 0; i < 128; i++) + datain[i] = 127; + i2c_read(SPD_EEPROM_ADDRESS,0,1,datain,128); +#ifdef SDRAM_DEBUG + serial_puts ("\ni2c_read returns "); + write_hex (i); + serial_puts ("\n"); +#endif + +#ifdef SDRAM_DEBUG + for (i = 0; i < 128; i++) { + write_hex (datain[i]); + serial_puts (" "); + if (((i + 1) % 16) == 0) + serial_puts ("\n"); + } + serial_puts ("\n"); +#endif + spd_chksum = 0; + for (i = 0; i < 63; i++) { + spd_chksum += datain[i]; + } /* endfor */ + if (datain[63] != spd_chksum) { +#ifdef SDRAM_DEBUG + serial_puts ("SPD chksum: 0x"); + write_hex (datain[63]); + serial_puts (" != calc. chksum: 0x"); + write_hex (spd_chksum); + serial_puts ("\n"); +#endif + SDRAM_err ("SPD checksum Error"); + } + /* SPD seems to be ok, use it */ + + /* get SPD version */ + spd_version = datain[62]; + + /* do some sanity checks on the kind of RAM */ + if ((datain[0] < 0x80) || /* less than 128 valid bytes in SPD */ + (datain[2] != 0x04) || /* if not SDRAM */ + (!((datain[6] == 0x40) || (datain[6] == 0x48))) || /* or not (64 Bit or 72 Bit) */ + (datain[7] != 0x00) || (datain[8] != 0x01) || /* or not LVTTL signal levels */ + (datain[126] == 0x66)) /* or a 66MHz modules */ + SDRAM_err ("unsupported SDRAM"); +#ifdef SDRAM_DEBUG + serial_puts ("SDRAM sanity ok\n"); +#endif + + /* get number of rows/cols/banks out of byte 3+4+5 */ + rows = datain[3]; + cols = datain[4]; + banks = datain[5]; + + /* get number of SDRAM banks out of byte 17 and + supported CAS latencies out of byte 18 */ + sdram_banks = datain[17]; + supported_cal = datain[18] & ~0x81; + + while (t->mode != 0) { + if ((t->row == rows) && (t->col == cols) + && (t->bank == sdram_banks)) + break; + t++; + } /* endwhile */ + +#ifdef SDRAM_DEBUG + serial_puts ("rows: "); + write_hex (rows); + serial_puts (" cols: "); + write_hex (cols); + serial_puts (" banks: "); + write_hex (banks); + serial_puts (" mode: "); + write_hex (t->mode); + serial_puts ("\n"); +#endif + if (t->mode == 0) + SDRAM_err ("unsupported SDRAM"); + /* get tRP, tRCD, tRAS and density from byte 27+29+30+31 */ +#ifdef SDRAM_DEBUG + serial_puts ("tRP: "); + write_hex (datain[27]); + serial_puts ("\ntRCD: "); + write_hex (datain[29]); + serial_puts ("\ntRAS: "); + write_hex (datain[30]); + serial_puts ("\n"); +#endif + + trp_clocks = (NSto10PS (datain[27]) + (tmemclk - 1)) / tmemclk; + trcd_clocks = (NSto10PS (datain[29]) + (tmemclk - 1)) / tmemclk; + tras_clocks = (NSto10PS (datain[30]) + (tmemclk - 1)) / tmemclk; + density = datain[31]; + + /* trc_clocks is sum of trp_clocks + tras_clocks */ + trc_clocks = trp_clocks + tras_clocks; + /* ctp = ((trp + tras) - trp - trcd) => tras - trcd */ + tctp_clocks = + ((NSto10PS (datain[30]) - NSto10PS (datain[29])) + + (tmemclk - 1)) / tmemclk; + +#ifdef SDRAM_DEBUG + serial_puts ("c_RP: "); + write_hex (trp_clocks); + serial_puts ("\nc_RCD: "); + write_hex (trcd_clocks); + serial_puts ("\nc_RAS: "); + write_hex (tras_clocks); + serial_puts ("\nc_RC: (RP+RAS): "); + write_hex (trc_clocks); + serial_puts ("\nc_CTP: ((RP+RAS)-RP-RCD): "); + write_hex (tctp_clocks); + serial_puts ("\nt_CTP: RAS - RCD: "); + write_hex ((unsigned + char) ((NSto10PS (datain[30]) - + NSto10PS (datain[29])) >> 8)); + write_hex ((unsigned char) (NSto10PS (datain[30]) - NSto10PS (datain[29]))); + serial_puts ("\ntmemclk: "); + write_hex ((unsigned char) (tmemclk >> 8)); + write_hex ((unsigned char) (tmemclk)); + serial_puts ("\n"); +#endif + + + cal_val = 255; + for (i = 6, cal_index = 0; (i > 0) && (cal_index < 3); i--) { + /* is this CAS latency supported ? */ + if ((supported_cal >> i) & 0x01) { + buf[0] = datain[cal_indextable[cal_index]]; + if (cal_index < 2) { + if (NS10to10PS (buf[0], spd_version) <= tmemclk) + cal_val = i; + } else { + /* SPD bytes 25+26 have another format */ + if (NS4to10PS (buf[0], spd_version) <= tmemclk) + cal_val = i; + } /* endif */ + cal_index++; + } /* endif */ + } /* endfor */ +#ifdef SDRAM_DEBUG + serial_puts ("CAL: "); + write_hex (cal_val + 1); + serial_puts ("\n"); +#endif + + if (cal_val == 255) + SDRAM_err ("unsupported SDRAM"); + + /* get SDRAM timing register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_TR); + tmp = mfdcr (SDRAM0_CFGDATA) & ~0x018FC01F; + /* insert CASL value */ +/* tmp |= ((unsigned long)cal_val) << 23; */ + tmp |= ((unsigned long) cal_val) << 23; + /* insert PTA value */ + tmp |= ((unsigned long) (trp_clocks - 1)) << 18; + /* insert CTP value */ +/* tmp |= ((unsigned long)(trc_clocks - trp_clocks - trcd_clocks - 1)) << 16; */ + tmp |= ((unsigned long) (trc_clocks - trp_clocks - trcd_clocks)) << 16; + /* insert LDF (always 01) */ + tmp |= ((unsigned long) 0x01) << 14; + /* insert RFTA value */ + tmp |= ((unsigned long) (trc_clocks - 4)) << 2; + /* insert RCD value */ + tmp |= ((unsigned long) (trcd_clocks - 1)) << 0; + +#ifdef SDRAM_DEBUG + serial_puts ("sdtr: "); + write_4hex (tmp); + serial_puts ("\n"); +#endif + + /* write SDRAM timing register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_TR); + mtdcr (SDRAM0_CFGDATA, tmp); + baseaddr = CONFIG_SYS_SDRAM_BASE; + bank_size = (((unsigned long) density) << 22) / 2; + /* insert AM value */ + tmp = ((unsigned long) t->mode - 1) << 13; + /* insert SZ value; */ + switch (bank_size) { + case 0x00400000: + tmp |= ((unsigned long) 0x00) << 17; + break; + case 0x00800000: + tmp |= ((unsigned long) 0x01) << 17; + break; + case 0x01000000: + tmp |= ((unsigned long) 0x02) << 17; + break; + case 0x02000000: + tmp |= ((unsigned long) 0x03) << 17; + break; + case 0x04000000: + tmp |= ((unsigned long) 0x04) << 17; + break; + case 0x08000000: + tmp |= ((unsigned long) 0x05) << 17; + break; + case 0x10000000: + tmp |= ((unsigned long) 0x06) << 17; + break; + default: + SDRAM_err ("unsupported SDRAM"); + } /* endswitch */ + /* get SDRAM bank 0 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); + bank = mfdcr (SDRAM0_CFGDATA) & ~0xFFCEE001; + bank |= (baseaddr | tmp | 0x01); +#ifdef SDRAM_DEBUG + serial_puts ("bank0: baseaddr: "); + write_4hex (baseaddr); + serial_puts (" banksize: "); + write_4hex (bank_size); + serial_puts (" mb0cf: "); + write_4hex (bank); + serial_puts ("\n"); +#endif + baseaddr += bank_size; + sdram_size += bank_size; + + /* write SDRAM bank 0 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); + mtdcr (SDRAM0_CFGDATA, bank); + + /* get SDRAM bank 1 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B1CR); + bank = mfdcr (SDRAM0_CFGDATA) & ~0xFFCEE001; + sdram_size = 0; + +#ifdef SDRAM_DEBUG + serial_puts ("bank1: baseaddr: "); + write_4hex (baseaddr); + serial_puts (" banksize: "); + write_4hex (bank_size); +#endif + if (banks == 2) { + bank |= (baseaddr | tmp | 0x01); + baseaddr += bank_size; + sdram_size += bank_size; + } /* endif */ +#ifdef SDRAM_DEBUG + serial_puts (" mb1cf: "); + write_4hex (bank); + serial_puts ("\n"); +#endif + /* write SDRAM bank 1 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B1CR); + mtdcr (SDRAM0_CFGDATA, bank); + + /* get SDRAM bank 2 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B2CR); + bank = mfdcr (SDRAM0_CFGDATA) & ~0xFFCEE001; + + bank |= (baseaddr | tmp | 0x01); + +#ifdef SDRAM_DEBUG + serial_puts ("bank2: baseaddr: "); + write_4hex (baseaddr); + serial_puts (" banksize: "); + write_4hex (bank_size); + serial_puts (" mb2cf: "); + write_4hex (bank); + serial_puts ("\n"); +#endif + + baseaddr += bank_size; + sdram_size += bank_size; + + /* write SDRAM bank 2 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B2CR); + mtdcr (SDRAM0_CFGDATA, bank); + + /* get SDRAM bank 3 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B3CR); + bank = mfdcr (SDRAM0_CFGDATA) & ~0xFFCEE001; + +#ifdef SDRAM_DEBUG + serial_puts ("bank3: baseaddr: "); + write_4hex (baseaddr); + serial_puts (" banksize: "); + write_4hex (bank_size); +#endif + + if (banks == 2) { + bank |= (baseaddr | tmp | 0x01); + baseaddr += bank_size; + sdram_size += bank_size; + } + /* endif */ +#ifdef SDRAM_DEBUG + serial_puts (" mb3cf: "); + write_4hex (bank); + serial_puts ("\n"); +#endif + + /* write SDRAM bank 3 register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B3CR); + mtdcr (SDRAM0_CFGDATA, bank); + + + /* get SDRAM refresh interval register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_RTR); + tmp = mfdcr (SDRAM0_CFGDATA) & ~0x3FF80000; + + if (tmemclk < NSto10PS (16)) + tmp |= 0x05F00000; + else + tmp |= 0x03F80000; + + /* write SDRAM refresh interval register */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_RTR); + mtdcr (SDRAM0_CFGDATA, tmp); + + /* enable SDRAM controller with no ECC, 32-bit SDRAM width, 16 byte burst */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); + tmp = (mfdcr (SDRAM0_CFGDATA) & ~0xFFE00000) | 0x80E00000; + mtdcr (SDRAM0_CFGADDR, SDRAM0_CFG); + mtdcr (SDRAM0_CFGDATA, tmp); + + + /*-------------------------------------------------------------------------+ + | Interrupt controller setup for the PIP405 board. + | Note: IRQ 0-15 405GP internally generated; active high; level sensitive + | IRQ 16 405GP internally generated; active low; level sensitive + | IRQ 17-24 RESERVED + | IRQ 25 (EXT IRQ 0) SouthBridg; active low; level sensitive + | IRQ 26 (EXT IRQ 1) NMI: active low; level sensitive + | IRQ 27 (EXT IRQ 2) SMI: active Low; level sensitive + | IRQ 28 (EXT IRQ 3) PCI SLOT 3; active low; level sensitive + | IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive + | IRQ 30 (EXT IRQ 5) PCI SLOT 1; active low; level sensitive + | IRQ 31 (EXT IRQ 6) PCI SLOT 0; active low; level sensitive + | Note for PIP405 board: + | An interrupt taken for the SouthBridge (IRQ 25) indicates that + | the Interrupt Controller in the South Bridge has caused the + | interrupt. The IC must be read to determine which device + | caused the interrupt. + | + +-------------------------------------------------------------------------*/ + mtdcr (UIC0SR, 0xFFFFFFFF); /* clear all ints */ + mtdcr (UIC0ER, 0x00000000); /* disable all ints */ + mtdcr (UIC0CR, 0x00000000); /* set all to be non-critical (for now) */ + mtdcr (UIC0PR, 0xFFFFFF80); /* set int polarities */ + mtdcr (UIC0TR, 0x10000000); /* set int trigger levels */ + mtdcr (UIC0VCR, 0x00000001); /* set vect base=0,INT0 highest priority */ + mtdcr (UIC0SR, 0xFFFFFFFF); /* clear all ints */ + + return 0; +} + + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + char s[50]; + unsigned char bc; + int i; + backup_t *b = (backup_t *) s; + + puts ("Board: "); + + i = getenv_f("serial#", (char *)s, 32); + if ((i == 0) || strncmp ((char *)s, "PIP405", 6)) { + get_backup_values (b); + if (strncmp (b->signature, "MPL\0", 4) != 0) { + puts ("### No HW ID - assuming PIP405"); + } else { + b->serial_name[6] = 0; + printf ("%s SN: %s", b->serial_name, + &b->serial_name[7]); + } + } else { + s[6] = 0; + printf ("%s SN: %s", s, &s[7]); + } + bc = in8 (CONFIG_PORT_ADDR); + printf (" Boot Config: 0x%x\n", bc); + return (0); +} + + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +/* + initdram(int board_type) reads EEPROM via I2c. EEPROM contains all of + the necessary info for SDRAM controller configuration +*/ +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +static int test_dram (unsigned long ramsize); + +phys_size_t initdram (int board_type) +{ + unsigned long bank_reg[4], tmp, bank_size; + int i, ds; + unsigned long TotalSize; + + ds = 0; + /* since the DRAM controller is allready set up, + * calculate the size with the bank registers + */ + mtdcr (SDRAM0_CFGADDR, SDRAM0_B0CR); + bank_reg[0] = mfdcr (SDRAM0_CFGDATA); + mtdcr (SDRAM0_CFGADDR, SDRAM0_B1CR); + bank_reg[1] = mfdcr (SDRAM0_CFGDATA); + mtdcr (SDRAM0_CFGADDR, SDRAM0_B2CR); + bank_reg[2] = mfdcr (SDRAM0_CFGDATA); + mtdcr (SDRAM0_CFGADDR, SDRAM0_B3CR); + bank_reg[3] = mfdcr (SDRAM0_CFGDATA); + TotalSize = 0; + for (i = 0; i < 4; i++) { + if ((bank_reg[i] & 0x1) == 0x1) { + tmp = (bank_reg[i] >> 17) & 0x7; + bank_size = 4 << tmp; + TotalSize += bank_size; + } else + ds = 1; + } + if (ds == 1) + printf ("single-sided DIMM "); + else + printf ("double-sided DIMM "); + test_dram (TotalSize * 1024 * 1024); + /* bank 2 (SDRAM Clock 2) is not usable if 133MHz SDRAM IF */ + (void) get_clocks(); + if (gd->cpu_clk > 220000000) + TotalSize /= 2; + return (TotalSize * 1024 * 1024); +} + +/* ------------------------------------------------------------------------- */ + + +static int test_dram (unsigned long ramsize) +{ + /* not yet implemented */ + return (1); +} + + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +int misc_init_r (void) +{ + /* adjust flash start and size as well as the offset */ + gd->bd->bi_flashstart=0-flash_info[0].size; + gd->bd->bi_flashsize=flash_info[0].size-CONFIG_SYS_MONITOR_LEN; + gd->bd->bi_flashoffset=0; + + /* if PIP405 has booted from PCI, reset CCR0[24] as described in errata PCI_18 */ + if (mfdcr(CPC0_PSR) & PSR_ROM_LOC) + mtspr(SPRN_CCR0, (mfspr(SPRN_CCR0) & ~0x80)); + + return (0); +} + +/*************************************************************************** + * some helping routines + */ + +int overwrite_console (void) +{ + return (in8 (CONFIG_PORT_ADDR) & 0x1); /* return TRUE if console should be overwritten */ +} + + +extern int isa_init (void); + + +void print_pip405_rev (void) +{ + unsigned char part, vers, cfg; + + part = in8 (PLD_PART_REG); + vers = in8 (PLD_VERS_REG); + cfg = in8 (PLD_BOARD_CFG_REG); + printf ("Rev: PIP405-%d Rev %c PLD%d %d PLD%d %d\n", + 16 - ((cfg >> 4) & 0xf), (cfg & 0xf) + 'A', part & 0xf, + vers & 0xf, (part >> 4) & 0xf, (vers >> 4) & 0xf); +} + +extern void check_env(void); + + +int last_stage_init (void) +{ + print_pip405_rev (); + isa_init (); + stdio_print_current_devices (); + check_env(); + return 0; +} + +/************************************************************************ +* Print PIP405 Info +************************************************************************/ +void print_pip405_info (void) +{ + unsigned char part, vers, cfg, ledu, sysman, flashcom, can, serpwr, + compwr, nicvga, scsirst; + + part = in8 (PLD_PART_REG); + vers = in8 (PLD_VERS_REG); + cfg = in8 (PLD_BOARD_CFG_REG); + ledu = in8 (PLD_LED_USER_REG); + sysman = in8 (PLD_SYS_MAN_REG); + flashcom = in8 (PLD_FLASH_COM_REG); + can = in8 (PLD_CAN_REG); + serpwr = in8 (PLD_SER_PWR_REG); + compwr = in8 (PLD_COM_PWR_REG); + nicvga = in8 (PLD_NIC_VGA_REG); + scsirst = in8 (PLD_SCSI_RST_REG); + printf ("PLD Part %d version %d\n", + part & 0xf, vers & 0xf); + printf ("PLD Part %d version %d\n", + (part >> 4) & 0xf, (vers >> 4) & 0xf); + printf ("Board Revision %c\n", (cfg & 0xf) + 'A'); + printf ("Population Options %d %d %d %d\n", + (cfg >> 4) & 0x1, (cfg >> 5) & 0x1, + (cfg >> 6) & 0x1, (cfg >> 7) & 0x1); + printf ("User LED0 %s User LED1 %s\n", + ((ledu & 0x1) == 0x1) ? "on" : "off", + ((ledu & 0x2) == 0x2) ? "on" : "off"); + printf ("Additionally Options %d %d\n", + (ledu >> 2) & 0x1, (ledu >> 3) & 0x1); + printf ("User Config Switch %d %d %d %d\n", + (ledu >> 4) & 0x1, (ledu >> 5) & 0x1, + (ledu >> 6) & 0x1, (ledu >> 7) & 0x1); + switch (sysman & 0x3) { + case 0: + printf ("PCI Clocks are running\n"); + break; + case 1: + printf ("PCI Clocks are stopped in POS State\n"); + break; + case 2: + printf ("PCI Clocks are stopped when PCI_STP# is asserted\n"); + break; + case 3: + printf ("PCI Clocks are stopped\n"); + break; + } + switch ((sysman >> 2) & 0x3) { + case 0: + printf ("Main Clocks are running\n"); + break; + case 1: + printf ("Main Clocks are stopped in POS State\n"); + break; + case 2: + case 3: + printf ("PCI Clocks are stopped\n"); + break; + } + printf ("INIT asserts %sINT2# (SMI)\n", + ((sysman & 0x10) == 0x10) ? "" : "not "); + printf ("INIT asserts %sINT1# (NMI)\n", + ((sysman & 0x20) == 0x20) ? "" : "not "); + printf ("INIT occured %d\n", (sysman >> 6) & 0x1); + printf ("SER1 is routed to %s\n", + ((flashcom & 0x1) == 0x1) ? "RS485" : "RS232"); + printf ("COM2 is routed to %s\n", + ((flashcom & 0x2) == 0x2) ? "RS485" : "RS232"); + printf ("RS485 is configured as %s duplex\n", + ((flashcom & 0x4) == 0x4) ? "full" : "half"); + printf ("RS485 is connected to %s\n", + ((flashcom & 0x8) == 0x8) ? "COM1" : "COM2"); + printf ("SER1 uses handshakes %s\n", + ((flashcom & 0x10) == 0x10) ? "DTR/DSR" : "RTS/CTS"); + printf ("Bootflash is %swriteprotected\n", + ((flashcom & 0x20) == 0x20) ? "not " : ""); + printf ("Bootflash VPP is %s\n", + ((flashcom & 0x40) == 0x40) ? "on" : "off"); + printf ("Bootsector is %swriteprotected\n", + ((flashcom & 0x80) == 0x80) ? "not " : ""); + switch ((can) & 0x3) { + case 0: + printf ("CAN Controller is on address 0x1000..0x10FF\n"); + break; + case 1: + printf ("CAN Controller is on address 0x8000..0x80FF\n"); + break; + case 2: + printf ("CAN Controller is on address 0xE000..0xE0FF\n"); + break; + case 3: + printf ("CAN Controller is disabled\n"); + break; + } + switch ((can >> 2) & 0x3) { + case 0: + printf ("CAN Controller Reset is ISA Reset\n"); + break; + case 1: + printf ("CAN Controller Reset is ISA Reset and POS State\n"); + break; + case 2: + case 3: + printf ("CAN Controller is in reset\n"); + break; + } + if (((can >> 4) < 3) || ((can >> 4) == 8) || ((can >> 4) == 13)) + printf ("CAN Interrupt is disabled\n"); + else + printf ("CAN Interrupt is ISA INT%d\n", (can >> 4) & 0xf); + switch (serpwr & 0x3) { + case 0: + printf ("SER0 Drivers are enabled\n"); + break; + case 1: + printf ("SER0 Drivers are disabled in the POS state\n"); + break; + case 2: + case 3: + printf ("SER0 Drivers are disabled\n"); + break; + } + switch ((serpwr >> 2) & 0x3) { + case 0: + printf ("SER1 Drivers are enabled\n"); + break; + case 1: + printf ("SER1 Drivers are disabled in the POS state\n"); + break; + case 2: + case 3: + printf ("SER1 Drivers are disabled\n"); + break; + } + switch (compwr & 0x3) { + case 0: + printf ("COM1 Drivers are enabled\n"); + break; + case 1: + printf ("COM1 Drivers are disabled in the POS state\n"); + break; + case 2: + case 3: + printf ("COM1 Drivers are disabled\n"); + break; + } + switch ((compwr >> 2) & 0x3) { + case 0: + printf ("COM2 Drivers are enabled\n"); + break; + case 1: + printf ("COM2 Drivers are disabled in the POS state\n"); + break; + case 2: + case 3: + printf ("COM2 Drivers are disabled\n"); + break; + } + switch ((nicvga) & 0x3) { + case 0: + printf ("PHY is running\n"); + break; + case 1: + printf ("PHY is in Power save mode in POS state\n"); + break; + case 2: + case 3: + printf ("PHY is in Power save mode\n"); + break; + } + switch ((nicvga >> 2) & 0x3) { + case 0: + printf ("VGA is running\n"); + break; + case 1: + printf ("VGA is in Power save mode in POS state\n"); + break; + case 2: + case 3: + printf ("VGA is in Power save mode\n"); + break; + } + printf ("PHY is %sreseted\n", ((nicvga & 0x10) == 0x10) ? "" : "not "); + printf ("VGA is %sreseted\n", ((nicvga & 0x20) == 0x20) ? "" : "not "); + printf ("Reserved Configuration is %d %d\n", (nicvga >> 6) & 0x1, + (nicvga >> 7) & 0x1); + switch ((scsirst) & 0x3) { + case 0: + printf ("SCSI Controller is running\n"); + break; + case 1: + printf ("SCSI Controller is in Power save mode in POS state\n"); + break; + case 2: + case 3: + printf ("SCSI Controller is in Power save mode\n"); + break; + } + printf ("SCSI termination is %s\n", + ((scsirst & 0x4) == 0x4) ? "disabled" : "enabled"); + printf ("SCSI Controller is %sreseted\n", + ((scsirst & 0x10) == 0x10) ? "" : "not "); + printf ("IDE disks are %sreseted\n", + ((scsirst & 0x20) == 0x20) ? "" : "not "); + printf ("ISA Bus is %sreseted\n", + ((scsirst & 0x40) == 0x40) ? "" : "not "); + printf ("Super IO is %sreseted\n", + ((scsirst & 0x80) == 0x80) ? "" : "not "); +} + +void user_led0 (unsigned char on) +{ + if (on == TRUE) + out8 (PLD_LED_USER_REG, (in8 (PLD_LED_USER_REG) | 0x1)); + else + out8 (PLD_LED_USER_REG, (in8 (PLD_LED_USER_REG) & 0xfe)); +} + +void user_led1 (unsigned char on) +{ + if (on == TRUE) + out8 (PLD_LED_USER_REG, (in8 (PLD_LED_USER_REG) | 0x2)); + else + out8 (PLD_LED_USER_REG, (in8 (PLD_LED_USER_REG) & 0xfd)); +} + +void ide_set_reset (int idereset) +{ + /* if reset = 1 IDE reset will be asserted */ + unsigned char resreg; + + resreg = in8 (PLD_SCSI_RST_REG); + if (idereset == 1) + resreg |= 0x20; + else { + udelay(10000); + resreg &= 0xdf; + } + out8 (PLD_SCSI_RST_REG, resreg); +} diff --git a/u-boot/board/mpl/pip405/pip405.h b/u-boot/board/mpl/pip405/pip405.h new file mode 100644 index 0000000..704ab2c --- /dev/null +++ b/u-boot/board/mpl/pip405/pip405.h @@ -0,0 +1,148 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + */ + /**************************************************************************** + * Global routines used for PIP405 + *****************************************************************************/ + +#ifndef __ASSEMBLY__ + +extern int mem_test(unsigned long start, unsigned long ramsize,int mode); + +void print_pip405_info(void); + +void user_led0(unsigned char on); +void user_led1(unsigned char on); + + +#define PLD_BASE_ADDRESS CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x800 +#define PLD_PART_REG PLD_BASE_ADDRESS + 0 +#define PLD_VERS_REG PLD_BASE_ADDRESS + 1 +#define PLD_BOARD_CFG_REG PLD_BASE_ADDRESS + 2 +#define PLD_LED_USER_REG PLD_BASE_ADDRESS + 3 +#define PLD_SYS_MAN_REG PLD_BASE_ADDRESS + 4 +#define PLD_FLASH_COM_REG PLD_BASE_ADDRESS + 5 +#define PLD_CAN_REG PLD_BASE_ADDRESS + 6 +#define PLD_SER_PWR_REG PLD_BASE_ADDRESS + 7 +#define PLD_COM_PWR_REG PLD_BASE_ADDRESS + 8 +#define PLD_NIC_VGA_REG PLD_BASE_ADDRESS + 9 +#define PLD_SCSI_RST_REG PLD_BASE_ADDRESS + 0xA + +#define PIIX4_VENDOR_ID 0x8086 +#define PIIX4_IDE_DEV_ID 0x7111 + +#endif + +/* timings */ + +/* CS Config register (CS7) */ +#define CONFIG_PORT_BME 0 /* Burst disable */ +#define CONFIG_PORT_TWE 255 /* 255 * 30ns 120ns Waitstates (access=TWT+1+TH) */ +#define CONFIG_PORT_CSN 1 /* Chipselect is driven inactive for 1 Cycle BTW transfers */ +#define CONFIG_PORT_OEN 1 /* Cycles from CS low to OE low */ +#define CONFIG_PORT_WBN 1 /* Cycles from CS low to WE low */ +#define CONFIG_PORT_WBF 1 /* Cycles from WE high to CS high */ +#define CONFIG_PORT_TH 2 /* Number of hold cycles after transfer */ +#define CONFIG_PORT_RE 0 /* Ready disabled */ +#define CONFIG_PORT_SOR 1 /* Sample on Ready disabled */ +#define CONFIG_PORT_BEM 0 /* Byte Write only active on Write cycles */ +#define CONFIG_PORT_PEN 0 /* Parity disable */ +#define CONFIG_PORT_AP ((CONFIG_PORT_BME << 31) + (CONFIG_PORT_TWE << 23) + (CONFIG_PORT_CSN << 18) + (CONFIG_PORT_OEN << 16) + (CONFIG_PORT_WBN << 14) + \ + (CONFIG_PORT_WBF << 12) + (CONFIG_PORT_TH << 9) + (CONFIG_PORT_RE << 8) + (CONFIG_PORT_SOR << 7) + (CONFIG_PORT_BEM << 6) + (CONFIG_PORT_PEN << 5)) + +/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */ +#define CONFIG_PORT_BS 0 /* 1 MByte */ +/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */ +#define CONFIG_PORT_BU 3 /* R/W */ +/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */ +#define CONFIG_PORT_BW 0 /* 16Bit */ +#define CONFIG_PORT_CR ((CONFIG_PORT_ADDR & 0xfff00000) + (CONFIG_PORT_BS << 17) + (CONFIG_PORT_BU << 15) + (CONFIG_PORT_BW << 13)) + +/* Flash CS0 or CS 1 */ +/* 0x7F8FFE80 slowest timing at all... */ +#define FLASH_BME_B 1 /* Burst enable */ +#define FLASH_FWT_B 0x6 /* 6 * 30ns 210ns First Wait Access */ +#define FLASH_BWT_B 0x6 /* 6 * 30ns 210ns Burst Wait Access */ +#define FLASH_BME 0 /* Burst disable */ +#define FLASH_TWE 0xb/* 11 * 30ns 330ns Waitstates (access=TWT+1+TH) */ +#define FLASH_CSN 0 /* Chipselect is driven inactive for 1 Cycle BTW transfers */ +#define FLASH_OEN 1 /* Cycles from CS low to OE low */ +#define FLASH_WBN 1 /* Cycles from CS low to WE low */ +#define FLASH_WBF 1 /* Cycles from WE high to CS high */ +#define FLASH_TH 2 /* Number of hold cycles after transfer */ +#define FLASH_RE 0 /* Ready disabled */ +#define FLASH_SOR 1 /* Sample on Ready disabled */ +#define FLASH_BEM 0 /* Byte Write only active on Write cycles */ +#define FLASH_PEN 0 /* Parity disable */ +/* Access Parameter Register for non Boot */ +#define FLASH_AP ((FLASH_BME << 31) + (FLASH_TWE << 23) + (FLASH_CSN << 18) + (FLASH_OEN << 16) + (FLASH_WBN << 14) + \ + (FLASH_WBF << 12) + (FLASH_TH << 9) + (FLASH_RE << 8) + (FLASH_SOR << 7) + (FLASH_BEM << 6) + (FLASH_PEN << 5)) +/* Access Parameter Register for Boot */ +#define FLASH_AP_B ((FLASH_BME_B << 31) + (FLASH_FWT_B << 26) + (FLASH_BWT_B << 23) + (FLASH_CSN << 18) + (FLASH_OEN << 16) + (FLASH_WBN << 14) + \ + (FLASH_WBF << 12) + (FLASH_TH << 9) + (FLASH_RE << 8) + (FLASH_SOR << 7) + (FLASH_BEM << 6) + (FLASH_PEN << 5)) + +/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */ +#define FLASH_BS FLASH_SIZE_PRELIM /* 4 MByte */ +/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */ +#define FLASH_BU 3 /* R/W */ +/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */ +#define FLASH_BW 1 /* 16Bit */ +/* CR register for Boot */ +#define FLASH_CR_B ((FLASH_BASE_PRELIM & 0xfff00000) + (FLASH_BS << 17) + (FLASH_BU << 15) + (FLASH_BW << 13)) +/* CR register for non Boot */ +#define FLASH_CR ((MULTI_PURPOSE_SOCKET_ADDR & 0xfff00000) + (FLASH_BS << 17) + (FLASH_BU << 15) + (FLASH_BW << 13)) + +/* MPS CS1 or CS0 */ +/* Boot CS: */ +#define MPS_BME_B 1 /* Burst enable */ +#define MPS_FWT_B 0x6/* 6 * 30ns 210ns First Wait Access */ +#define MPS_BWT_B 0x6 /* 6 * 30ns 210ns Burst Wait Access */ +#define MPS_BME 0 /* Burst disable */ +#define MPS_TWE 0xb/* 11 * 30ns 330ns Waitstates (access=TWT+1+TH) */ +#define MPS_CSN 0 /* Chipselect is driven inactive for 1 Cycle BTW transfers */ +#define MPS_OEN 1 /* Cycles from CS low to OE low */ +#define MPS_WBN 1 /* Cycles from CS low to WE low */ +#define MPS_WBF 1 /* Cycles from WE high to CS high */ +#define MPS_TH 2 /* Number of hold cycles after transfer */ +#define MPS_RE 0 /* Ready disabled */ +#define MPS_SOR 1 /* Sample on Ready disabled */ +#define MPS_BEM 0 /* Byte Write only active on Write cycles */ +#define MPS_PEN 0 /* Parity disable */ +/* Access Parameter Register for non Boot */ +#define MPS_AP ((MPS_BME << 31) + (MPS_TWE << 23) + (MPS_CSN << 18) + (MPS_OEN << 16) + (MPS_WBN << 14) + \ + (MPS_WBF << 12) + (MPS_TH << 9) + (MPS_RE << 8) + (MPS_SOR << 7) + (MPS_BEM << 6) + (MPS_PEN << 5)) +/* Access Parameter Register for Boot */ +#define MPS_AP_B ((MPS_BME_B << 31) + (MPS_FWT_B << 26) + (MPS_BWT_B << 23) + (MPS_CSN << 18) + (MPS_OEN << 16) + (MPS_WBN << 14) + \ + (MPS_WBF << 12) + (MPS_TH << 9) + (MPS_RE << 8) + (MPS_SOR << 7) + (MPS_BEM << 6) + (MPS_PEN << 5)) + +/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */ +#define MPS_BS 2 /* 4 MByte */ +#define MPS_BS_B FLASH_SIZE_PRELIM /* 1 MByte */ +/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */ +#define MPS_BU 3 /* R/W */ +/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */ +#define MPS_BW 0 /* 8Bit */ +/* CR register for Boot */ +#define MPS_CR_B ((FLASH_BASE_PRELIM & 0xfff00000) + (MPS_BS << 17) + (MPS_BU << 15) + (MPS_BW << 13)) +/* CR register for non Boot */ +#define MPS_CR ((MULTI_PURPOSE_SOCKET_ADDR & 0xfff00000) + (MPS_BS << 17) + (MPS_BU << 15) + (MPS_BW << 13)) diff --git a/u-boot/board/mpl/pip405/u-boot.lds.debug b/u-boot/board/mpl/pip405/u-boot.lds.debug new file mode 100644 index 0000000..0e9cdcf --- /dev/null +++ b/u-boot/board/mpl/pip405/u-boot.lds.debug @@ -0,0 +1,135 @@ +/* + * (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 + */ + +OUTPUT_ARCH(powerpc) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + lib/vsprintf.o (.text) + lib/crc32.o (.text) + arch/powerpc/lib/extable.o (.text) + + common/env_embedded.o(.text) + + *(.text) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/u-boot/board/mpl/vcma9/Makefile b/u-boot/board/mpl/vcma9/Makefile new file mode 100644 index 0000000..27cef1d --- /dev/null +++ b/u-boot/board/mpl/vcma9/Makefile @@ -0,0 +1,56 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)../common) +endif + +LIB = $(obj)lib$(BOARD).o + +COBJS := vcma9.o flash.o cmd_vcma9.o +COBJS += ../common/common_util.o + +SOBJS := lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/board/mpl/vcma9/cmd_vcma9.c b/u-boot/board/mpl/vcma9/cmd_vcma9.c new file mode 100644 index 0000000..0d5f46e --- /dev/null +++ b/u-boot/board/mpl/vcma9/cmd_vcma9.c @@ -0,0 +1,186 @@ +/* + * (C) Copyright 2002 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * adapted for VCMA9 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <command.h> +#include <net.h> +#include "vcma9.h" +#include "../common/common_util.h" + +#if defined(CONFIG_CS8900) +#include <../drivers/net/cs8900.h> + +static uchar cs8900_chksum(ushort data) +{ + return((data >> 8) & 0x00FF) + (data & 0x00FF); +} + +#endif + +DECLARE_GLOBAL_DATA_PTR; + +extern void print_vcma9_info(void); +extern int vcma9_cantest(int); +extern int vcma9_nandtest(void); +extern int vcma9_nanderase(void); +extern int vcma9_nandread(ulong); +extern int vcma9_nandwrite(ulong); +extern int vcma9_dactest(int); +extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + +/* ------------------------------------------------------------------------- */ + +int do_vcma9(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct eth_device *dev; + char cs8900_name[10]; + if (strcmp(argv[1], "info") == 0) + { + print_vcma9_info(); + return 0; + } +#if defined(CONFIG_CS8900) + if (strcmp(argv[1], "cs8900") == 0) { + sprintf(cs8900_name, "%s-0", CS8900_DRIVERNAME); + dev = eth_get_dev_by_name(cs8900_name); + if (!dev) { + printf("Couldn't find CS8900 driver"); + return 0; + } + if (strcmp(argv[2], "read") == 0) { + uchar addr; ushort data; + + addr = simple_strtoul(argv[3], NULL, 16); + cs8900_e2prom_read(dev, addr, &data); + printf("0x%2.2X: 0x%4.4X\n", addr, data); + } else if (strcmp(argv[2], "write") == 0) { + uchar addr; ushort data; + + addr = simple_strtoul(argv[3], NULL, 16); + data = simple_strtoul(argv[4], NULL, 16); + cs8900_e2prom_write(dev, addr, data); + } else if (strcmp(argv[2], "setaddr") == 0) { + uchar addr, i, csum; ushort data; + uchar ethaddr[6]; + + /* check for valid ethaddr */ + if (eth_getenv_enetaddr("ethaddr", ethaddr)) { + addr = 1; + data = 0x2158; + cs8900_e2prom_write(dev, addr, data); + csum = cs8900_chksum(data); + addr++; + for (i = 0; i < 6; i+=2) { + data = ethaddr[i+1] << 8 | + ethaddr[i]; + cs8900_e2prom_write(dev, addr, data); + csum += cs8900_chksum(data); + addr++; + } + /* calculate header link byte */ + data = 0xA100 | (addr * 2); + cs8900_e2prom_write(dev, 0, data); + csum += cs8900_chksum(data); + /* write checksum word */ + cs8900_e2prom_write(dev, addr, (0 - csum) << 8); + } else { + puts("\nplease defined 'ethaddr'\n"); + } + } else if (strcmp(argv[2], "dump") == 0) { + uchar addr = 0, endaddr, csum; ushort data; + + puts("Dump of CS8900 config device: "); + cs8900_e2prom_read(dev, addr, &data); + if ((data & 0xE000) == 0xA000) { + endaddr = (data & 0x00FF) / 2; + csum = cs8900_chksum(data); + for (addr = 1; addr <= endaddr; addr++) { + cs8900_e2prom_read(dev, addr, &data); + printf("\n0x%2.2X: 0x%4.4X", addr, data); + csum += cs8900_chksum(data); + } + printf("\nChecksum: %s", (csum == 0) ? "ok" : "wrong"); + } else { + puts("no valid config found"); + } + puts("\n"); + } + + return 0; + } +#endif +#if 0 + if (strcmp(argv[1], "cantest") == 0) { + if (argc >= 3) + vcma9_cantest(strcmp(argv[2], "s") ? 0 : 1); + else + vcma9_cantest(0); + return 0; + } + if (strcmp(argv[1], "nandtest") == 0) { + vcma9_nandtest(); + return 0; + } + if (strcmp(argv[1], "nanderase") == 0) { + vcma9_nanderase(); + return 0; + } + if (strcmp(argv[1], "nandread") == 0) { + ulong offset = 0; + + if (argc >= 3) + offset = simple_strtoul(argv[2], NULL, 16); + + vcma9_nandread(offset); + return 0; + } + if (strcmp(argv[1], "nandwrite") == 0) { + ulong offset = 0; + + if (argc >= 3) + offset = simple_strtoul(argv[2], NULL, 16); + + vcma9_nandwrite(offset); + return 0; + } + if (strcmp(argv[1], "dactest") == 0) { + if (argc >= 3) + vcma9_dactest(strcmp(argv[2], "s") ? 0 : 1); + else + vcma9_dactest(0); + return 0; + } +#endif + + return (do_mplcommon(cmdtp, flag, argc, argv)); +} + +U_BOOT_CMD( + vcma9, 6, 1, do_vcma9, + "VCMA9 specific commands", + "flash mem [SrcAddr]\n - updates U-Boot with image in memory" +); diff --git a/u-boot/board/mpl/vcma9/config.mk b/u-boot/board/mpl/vcma9/config.mk new file mode 100644 index 0000000..e345913 --- /dev/null +++ b/u-boot/board/mpl/vcma9/config.mk @@ -0,0 +1,24 @@ +# +# (C) Copyright 2002, 2003 +# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> +# +# MPL VCMA9 board with S3C2410X (ARM920T) cpu +# +# see http://www.mpl.ch/ for more information about the MPL VCMA9 +# + +# +# MPL VCMA9 has 1 bank of minimal 16 MB DRAM +# from 0x30000000 +# +# Linux-Kernel is expected to be at 3000'8000, entry 3000'8000 +# optionally with a ramdisk at 3040'0000 +# +# we load ourself to 33F8'0000 +# +# download area is 3080'0000 +# + + +#CONFIG_SYS_TEXT_BASE = 0x30F80000 +CONFIG_SYS_TEXT_BASE = 0x33F80000 diff --git a/u-boot/board/mpl/vcma9/flash.c b/u-boot/board/mpl/vcma9/flash.c new file mode 100644 index 0000000..7abf9cf --- /dev/null +++ b/u-boot/board/mpl/vcma9/flash.c @@ -0,0 +1,432 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +ulong myflush (void); + + +#define FLASH_BANK_SIZE PHYS_FLASH_SIZE +#define MAIN_SECT_SIZE 0x10000 /* 64 KB */ + +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; + + +#define CMD_READ_ARRAY 0x000000F0 +#define CMD_UNLOCK1 0x000000AA +#define CMD_UNLOCK2 0x00000055 +#define CMD_ERASE_SETUP 0x00000080 +#define CMD_ERASE_CONFIRM 0x00000030 +#define CMD_PROGRAM 0x000000A0 +#define CMD_UNLOCK_BYPASS 0x00000020 + +#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 1))) +#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 1))) + +#define BIT_ERASE_DONE 0x00000080 +#define BIT_RDY_MASK 0x00000080 +#define BIT_PROGRAM_ERROR 0x00000020 +#define BIT_TIMEOUT 0x80000000 /* our flag */ + +#define READY 1 +#define ERR 2 +#define TMO 4 + +/*----------------------------------------------------------------------- + */ + +ulong flash_init (void) +{ + int i, j; + ulong size = 0; + + for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { + ulong flashbase = 0; + + flash_info[i].flash_id = +#if defined(CONFIG_AMD_LV400) + (AMD_MANUFACT & FLASH_VENDMASK) | + (AMD_ID_LV400B & FLASH_TYPEMASK); +#elif defined(CONFIG_AMD_LV800) + (AMD_MANUFACT & FLASH_VENDMASK) | + (AMD_ID_LV800B & FLASH_TYPEMASK); +#else +#error "Unknown flash configured" +#endif + flash_info[i].size = FLASH_BANK_SIZE; + flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT; + memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT); + if (i == 0) + flashbase = PHYS_FLASH_1; + else + panic ("configured too many flash banks!\n"); + for (j = 0; j < flash_info[i].sector_count; j++) { + if (j <= 3) { + /* 1st one is 16 KB */ + if (j == 0) { + flash_info[i].start[j] = + flashbase + 0; + } + + /* 2nd and 3rd are both 8 KB */ + if ((j == 1) || (j == 2)) { + flash_info[i].start[j] = + flashbase + 0x4000 + (j - + 1) * + 0x2000; + } + + /* 4th 32 KB */ + if (j == 3) { + flash_info[i].start[j] = + flashbase + 0x8000; + } + } else { + flash_info[i].start[j] = + flashbase + (j - 3) * MAIN_SECT_SIZE; + } + } + size += flash_info[i].size; + } + + flash_protect (FLAG_PROTECT_SET, + CONFIG_SYS_FLASH_BASE, + CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1, + &flash_info[0]); + + flash_protect (FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + switch (info->flash_id & FLASH_VENDMASK) { + case (AMD_MANUFACT & FLASH_VENDMASK): + puts ("AMD: "); + break; + default: + puts ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case (AMD_ID_LV400B & FLASH_TYPEMASK): + puts ("1x Amd29LV400BB (4Mbit)\n"); + break; + case (AMD_ID_LV800B & FLASH_TYPEMASK): + puts ("1x Amd29LV800BB (8Mbit)\n"); + break; + default: + puts ("Unknown Chip Type\n"); + goto Done; + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + puts (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; i++) { + if ((i % 5) == 0) { + puts ("\n "); + } + printf (" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + puts ("\n"); + +Done: ; +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + ushort result; + int iflag, cflag, prot, sect; + int rc = ERR_OK; + int chip; + + /* first look for protection bits */ + + if (info->flash_id == FLASH_UNKNOWN) + return ERR_UNKNOWN_FLASH_TYPE; + + if ((s_first < 0) || (s_first > s_last)) { + return ERR_INVAL; + } + + if ((info->flash_id & FLASH_VENDMASK) != + (AMD_MANUFACT & FLASH_VENDMASK)) { + return ERR_UNKNOWN_FLASH_VENDOR; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + if (prot) + return ERR_PROTECTED; + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + cflag = icache_status (); + icache_disable (); + iflag = disable_interrupts (); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last && !ctrlc (); sect++) { + printf ("Erasing sector %2d ... ", sect); + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + if (info->protect[sect] == 0) { /* not protected */ + vu_short *addr = (vu_short *) (info->start[sect]); + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + *addr = CMD_ERASE_CONFIRM; + + /* wait until flash is ready */ + chip = 0; + + do { + result = *addr; + + /* check timeout */ + if (get_timer_masked () > + CONFIG_SYS_FLASH_ERASE_TOUT) { + MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + chip = TMO; + break; + } + + if (!chip + && (result & 0xFFFF) & BIT_ERASE_DONE) + chip = READY; + + if (!chip + && (result & 0xFFFF) & BIT_PROGRAM_ERROR) + chip = ERR; + + } while (!chip); + + MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + + if (chip == ERR) { + rc = ERR_PROG_ERROR; + goto outahere; + } + if (chip == TMO) { + rc = ERR_TIMOUT; + goto outahere; + } + + puts ("ok.\n"); + } else { /* it was protected */ + + puts ("protected!\n"); + } + } + + if (ctrlc ()) + puts ("User Interrupt!\n"); + + outahere: + /* allow flash to settle - wait 10 ms */ + udelay_masked (10000); + + if (iflag) + enable_interrupts (); + + if (cflag) + icache_enable (); + + return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash + */ + +static int write_hword (flash_info_t * info, ulong dest, ushort data) +{ + vu_short *addr = (vu_short *) dest; + ushort result; + int rc = ERR_OK; + int cflag, iflag; + int chip; + + /* + * Check if Flash is (sufficiently) erased + */ + result = *addr; + if ((result & data) != data) + return ERR_NOT_ERASED; + + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + cflag = icache_status (); + icache_disable (); + iflag = disable_interrupts (); + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + MEM_FLASH_ADDR1 = CMD_PROGRAM; + *addr = data; + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + /* wait until flash is ready */ + chip = 0; + do { + result = *addr; + + /* check timeout */ + if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) { + chip = ERR | TMO; + break; + } + if (!chip && ((result & 0x80) == (data & 0x80))) + chip = READY; + + if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) { + result = *addr; + + if ((result & 0x80) == (data & 0x80)) + chip = READY; + else + chip = ERR; + } + + } while (!chip); + + *addr = CMD_READ_ARRAY; + + if (chip == ERR || *addr != data) + rc = ERR_PROG_ERROR; + + if (iflag) + enable_interrupts (); + + if (cflag) + icache_enable (); + + return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong cp, wp; + int l; + int i, rc; + ushort data; + + wp = (addr & ~1); /* 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 << 8); + } + for (; i < 2 && cnt > 0; ++i) { + data = (data >> 8) | (*src++ << 8); + --cnt; + ++cp; + } + for (; cnt == 0 && i < 2; ++i, ++cp) { + data = (data >> 8) | (*(uchar *) cp << 8); + } + + if ((rc = write_hword (info, wp, data)) != 0) { + return (rc); + } + wp += 2; + } + + /* + * handle word aligned part + */ + while (cnt >= 2) { + data = *((vu_short *) src); + if ((rc = write_hword (info, wp, data)) != 0) { + return (rc); + } + src += 2; + wp += 2; + cnt -= 2; + } + + if (cnt == 0) { + return ERR_OK; + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) { + data = (data >> 8) | (*src++ << 8); + --cnt; + } + for (; i < 2; ++i, ++cp) { + data = (data >> 8) | (*(uchar *) cp << 8); + } + + return write_hword (info, wp, data); +} diff --git a/u-boot/board/mpl/vcma9/lowlevel_init.S b/u-boot/board/mpl/vcma9/lowlevel_init.S new file mode 100644 index 0000000..062e868 --- /dev/null +++ b/u-boot/board/mpl/vcma9/lowlevel_init.S @@ -0,0 +1,212 @@ +/* + * Memory Setup stuff - taken from blob memsetup.S + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * + * Modified for the Samsung SMDK2410 by + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <config.h> +#include <version.h> + + +/* some parameters for the board */ + +#define BWSCON 0x48000000 +#define PLD_BASE 0x2C000000 +#define SDRAM_REG 0x2C000106 + +/* BWSCON */ +#define DW8 (0x0) +#define DW16 (0x1) +#define DW32 (0x2) +#define WAIT (0x1<<2) +#define UBLB (0x1<<3) + +/* BANKSIZE */ +#define BURST_EN (0x1<<7) + +#define B1_BWSCON (DW16) +#define B2_BWSCON (DW32) +#define B3_BWSCON (DW32) +#define B4_BWSCON (DW16 + WAIT + UBLB) +#define B5_BWSCON (DW8 + UBLB) +#define B6_BWSCON (DW32) +#define B7_BWSCON (DW32) + +/* BANK0CON */ +#define B0_Tacs 0x0 /* 0clk */ +#define B0_Tcos 0x1 /* 1clk */ +/*#define B0_Tcos 0x0 0clk */ +#define B0_Tacc 0x7 /* 14clk */ +/*#define B0_Tacc 0x5 8clk */ +#define B0_Tcoh 0x0 /* 0clk */ +#define B0_Tah 0x0 /* 0clk */ +#define B0_Tacp 0x0 /* page mode is not used */ +#define B0_PMC 0x0 /* page mode disabled */ + +/* BANK1CON */ +#define B1_Tacs 0x0 /* 0clk */ +#define B1_Tcos 0x1 /* 1clk */ +/*#define B1_Tcos 0x0 0clk */ +#define B1_Tacc 0x7 /* 14clk */ +/*#define B1_Tacc 0x5 8clk */ +#define B1_Tcoh 0x0 /* 0clk */ +#define B1_Tah 0x0 /* 0clk */ +#define B1_Tacp 0x0 /* page mode is not used */ +#define B1_PMC 0x0 /* page mode disabled */ + +#define B2_Tacs 0x3 /* 4clk */ +#define B2_Tcos 0x3 /* 4clk */ +#define B2_Tacc 0x7 /* 14clk */ +#define B2_Tcoh 0x3 /* 4clk */ +#define B2_Tah 0x3 /* 4clk */ +#define B2_Tacp 0x0 /* page mode is not used */ +#define B2_PMC 0x0 /* page mode disabled */ + +#define B3_Tacs 0x3 /* 4clk */ +#define B3_Tcos 0x3 /* 4clk */ +#define B3_Tacc 0x7 /* 14clk */ +#define B3_Tcoh 0x3 /* 4clk */ +#define B3_Tah 0x3 /* 4clk */ +#define B3_Tacp 0x0 /* page mode is not used */ +#define B3_PMC 0x0 /* page mode disabled */ + +#define B4_Tacs 0x3 /* 4clk */ +#define B4_Tcos 0x1 /* 1clk */ +#define B4_Tacc 0x7 /* 14clk */ +#define B4_Tcoh 0x1 /* 1clk */ +#define B4_Tah 0x0 /* 0clk */ +#define B4_Tacp 0x0 /* page mode is not used */ +#define B4_PMC 0x0 /* page mode disabled */ + +#define B5_Tacs 0x0 /* 0clk */ +#define B5_Tcos 0x3 /* 4clk */ +#define B5_Tacc 0x5 /* 8clk */ +#define B5_Tcoh 0x2 /* 2clk */ +#define B5_Tah 0x1 /* 1clk */ +#define B5_Tacp 0x0 /* page mode is not used */ +#define B5_PMC 0x0 /* page mode disabled */ + +#define B6_MT 0x3 /* SDRAM */ +#define B6_Trcd 0x1 /* 3clk */ +#define B6_SCAN 0x2 /* 10bit */ + +#define B7_MT 0x3 /* SDRAM */ +#define B7_Trcd 0x1 /* 3clk */ +#define B7_SCAN 0x2 /* 10bit */ + +/* REFRESH parameter */ +#define REFEN 0x1 /* Refresh enable */ +#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */ +#define Trp 0x0 /* 2clk */ +#define Trc 0x3 /* 7clk */ +#define Tchr 0x2 /* 3clk */ +#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */ +/**************************************/ + +_TEXT_BASE: + .word CONFIG_SYS_TEXT_BASE + +.globl lowlevel_init +lowlevel_init: + /* memory control configuration */ + /* make r0 relative the current location so that it */ + /* reads SMRDATA out of FLASH rather than memory ! */ + ldr r0, =CSDATA + ldr r1, _TEXT_BASE + sub r0, r0, r1 + ldr r1, =BWSCON /* Bus Width Status Controller */ + add r2, r0, #CSDATA_END-CSDATA +0: + ldr r3, [r0], #4 + str r3, [r1], #4 + cmp r2, r0 + bne 0b + + /* PLD access is now possible */ + /* r0 == SDRAMDATA */ + /* r1 == SDRAM controller regs */ + ldr r2, =PLD_BASE + ldrb r3, [r2, #SDRAM_REG-PLD_BASE] + mov r4, #SDRAMDATA1_END-SDRAMDATA + /* calculate start and end point */ + mla r0, r3, r4, r0 + add r2, r0, r4 +0: + ldr r3, [r0], #4 + str r3, [r1], #4 + cmp r2, r0 + bne 0b + + /* everything is fine now */ + mov pc, lr + + .ltorg +/* the literal pools origin */ + +CSDATA: + .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) + .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) + .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) + .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) + .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) + .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) + .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) +CSDATA_END: + +SDRAMDATA: +/* 4Mx8x4 */ + .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) + .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) + .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) + .word 0x32 + BURST_EN + .word 0x30 + .word 0x30 +SDRAMDATA1_END: + +/* 8Mx8x4 (not implemented yet) */ + .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) + .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) + .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) + .word 0x32 + BURST_EN + .word 0x30 + .word 0x30 + +/* 2Mx8x4 (not implemented yet) */ + .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) + .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) + .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) + .word 0x32 + BURST_EN + .word 0x30 + .word 0x30 + +/* 4Mx8x2 (not implemented yet) */ + .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) + .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) + .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) + .word 0x32 + BURST_EN + .word 0x30 + .word 0x30 diff --git a/u-boot/board/mpl/vcma9/vcma9.c b/u-boot/board/mpl/vcma9/vcma9.c new file mode 100644 index 0000000..978e6fd --- /dev/null +++ b/u-boot/board/mpl/vcma9/vcma9.c @@ -0,0 +1,362 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <netdev.h> +#include <asm/arch/s3c24x0_cpu.h> +#include <stdio_dev.h> +#include <i2c.h> + +#include "vcma9.h" +#include "../common/common_util.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define FCLK_SPEED 1 + +#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */ +#define M_MDIV 0xC3 +#define M_PDIV 0x4 +#define M_SDIV 0x1 +#elif FCLK_SPEED==1 /* Fout = 202.8MHz */ +#define M_MDIV 0xA1 +#define M_PDIV 0x3 +#define M_SDIV 0x1 +#endif + +#define USB_CLOCK 1 + +#if USB_CLOCK==0 +#define U_M_MDIV 0xA1 +#define U_M_PDIV 0x3 +#define U_M_SDIV 0x1 +#elif USB_CLOCK==1 +#define U_M_MDIV 0x48 +#define U_M_PDIV 0x3 +#define U_M_SDIV 0x2 +#endif + +static inline void delay(unsigned long loops) +{ + __asm__ volatile ("1:\n" + "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0" (loops)); +} + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init(void) +{ + struct s3c24x0_clock_power * const clk_power = + s3c24x0_get_base_clock_power(); + struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio(); + + /* to reduce PLL lock time, adjust the LOCKTIME register */ + clk_power->locktime = 0xFFFFFF; + + /* configure MPLL */ + clk_power->mpllcon = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV); + + /* some delay between MPLL and UPLL */ + delay (4000); + + /* configure UPLL */ + clk_power->upllcon = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV); + + /* some delay between MPLL and UPLL */ + delay (8000); + + /* set up the I/O ports */ + gpio->gpacon = 0x007FFFFF; + gpio->gpbcon = 0x002AAAAA; + gpio->gpbup = 0x000002BF; + gpio->gpccon = 0xAAAAAAAA; + gpio->gpcup = 0x0000FFFF; + gpio->gpdcon = 0xAAAAAAAA; + gpio->gpdup = 0x0000FFFF; + gpio->gpecon = 0xAAAAAAAA; + gpio->gpeup = 0x000037F7; + gpio->gpfcon = 0x00000000; + gpio->gpfup = 0x00000000; + gpio->gpgcon = 0xFFEAFF5A; + gpio->gpgup = 0x0000F0DC; + gpio->gphcon = 0x0028AAAA; + gpio->gphup = 0x00000656; + + /* setup correct IRQ modes for NIC */ + /* rising edge mode */ + gpio->extint2 = (gpio->extint2 & ~(7<<8)) | (4<<8); + + /* select USB port 2 to be host or device (fix to host for now) */ + gpio->misccr |= 0x08; + + /* init serial */ + gd->baudrate = CONFIG_BAUDRATE; + gd->have_console = 1; + serial_init(); + + /* arch number of VCMA9-Board */ + gd->bd->bi_arch_number = MACH_TYPE_MPL_VCMA9; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x30000100; + + icache_enable(); + dcache_enable(); + + return 0; +} + +/* + * NAND flash initialization. + */ +#if defined(CONFIG_CMD_NAND) +extern ulong +nand_probe(ulong physadr); + + +static inline void NF_Reset(void) +{ + int i; + + NF_SetCE(NFCE_LOW); + NF_Cmd(0xFF); /* reset command */ + for(i = 0; i < 10; i++); /* tWB = 100ns. */ + NF_WaitRB(); /* wait 200~500us; */ + NF_SetCE(NFCE_HIGH); +} + + +static inline void NF_Init(void) +{ +#if 0 /* a little bit too optimistic */ +#define TACLS 0 +#define TWRPH0 3 +#define TWRPH1 0 +#else +#define TACLS 0 +#define TWRPH0 4 +#define TWRPH1 2 +#endif + + NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0)); + /*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */ + /* 1 1 1 1, 1 xxx, r xxx, r xxx */ + /* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */ + + NF_Reset(); +} + +void +nand_init(void) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + NF_Init(); +#ifdef DEBUG + printf("NAND flash probing at 0x%.8lX\n", (ulong)nand); +#endif + printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20); +} +#endif + +/* + * Get some Board/PLD Info + */ + +static u8 Get_PLD_ID(void) +{ + VCMA9_PLD * const pld = VCMA9_get_base_PLD(); + + return(pld->ID); +} + +static u8 Get_PLD_BOARD(void) +{ + VCMA9_PLD * const pld = VCMA9_get_base_PLD(); + + return(pld->BOARD); +} + +static u8 Get_PLD_SDRAM(void) +{ + VCMA9_PLD * const pld = VCMA9_get_base_PLD(); + + return(pld->SDRAM); +} + +static u8 Get_PLD_Version(void) +{ + return((Get_PLD_ID() >> 4) & 0x0F); +} + +static u8 Get_PLD_Revision(void) +{ + return(Get_PLD_ID() & 0x0F); +} + +#if 0 /* not used */ +static int Get_Board_Config(void) +{ + u8 config = Get_PLD_BOARD() & 0x03; + + if (config == 3) + return 1; + else + return 0; +} +#endif + +static uchar Get_Board_PCB(void) +{ + return(((Get_PLD_BOARD() >> 4) & 0x03) + 'A'); +} + +static u8 Get_SDRAM_ChipNr(void) +{ + switch ((Get_PLD_SDRAM() >> 4) & 0x0F) { + case 0: return 4; + case 1: return 1; + case 2: return 2; + default: return 0; + } +} + +static ulong Get_SDRAM_ChipSize(void) +{ + switch (Get_PLD_SDRAM() & 0x0F) { + case 0: return 16 * (1024*1024); + case 1: return 32 * (1024*1024); + case 2: return 8 * (1024*1024); + case 3: return 8 * (1024*1024); + default: return 0; + } +} +static const char * Get_SDRAM_ChipGeom(void) +{ + switch (Get_PLD_SDRAM() & 0x0F) { + case 0: return "4Mx8x4"; + case 1: return "8Mx8x4"; + case 2: return "2Mx8x4"; + case 3: return "4Mx8x2"; + default: return "unknown"; + } +} + +static void Show_VCMA9_Info(char *board_name, char *serial) +{ + printf("Board: %s SN: %s PCB Rev: %c PLD(%d,%d)\n", + board_name, serial, Get_Board_PCB(), Get_PLD_Version(), Get_PLD_Revision()); + printf("SDRAM: %d chips %s\n", Get_SDRAM_ChipNr(), Get_SDRAM_ChipGeom()); +} + +int dram_init(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = Get_SDRAM_ChipSize() * Get_SDRAM_ChipNr(); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + */ + +int checkboard(void) +{ + char s[50]; + int i; + backup_t *b = (backup_t *) s; + + i = getenv_f("serial#", s, 32); + if ((i < 0) || strncmp (s, "VCMA9", 5)) { + get_backup_values (b); + if (strncmp (b->signature, "MPL\0", 4) != 0) { + puts ("### No HW ID - assuming VCMA9"); + } else { + b->serial_name[5] = 0; + Show_VCMA9_Info(b->serial_name, &b->serial_name[6]); + } + } else { + s[5] = 0; + Show_VCMA9_Info(s, &s[6]); + } + /*printf("\n");*/ + return(0); +} + + +int last_stage_init(void) +{ + checkboard(); + stdio_print_current_devices(); + check_env(); + return 0; +} + +/*************************************************************************** + * some helping routines + */ +#if !CONFIG_USB_KEYBOARD +int overwrite_console(void) +{ + /* return TRUE if console should be overwritten */ + return 0; +} +#endif + +/************************************************************************ +* Print VCMA9 Info +************************************************************************/ +void print_vcma9_info(void) +{ + char s[50]; + int i; + + if ((i = getenv_f("serial#", s, 32)) < 0) { + puts ("### No HW ID - assuming VCMA9"); + printf("i %d", i*24); + } else { + s[5] = 0; + Show_VCMA9_Info(s, &s[6]); + } +} + +#ifdef CONFIG_CMD_NET +int board_eth_init(bd_t *bis) +{ + int rc = 0; +#ifdef CONFIG_CS8900 + rc = cs8900_initialize(0, CONFIG_CS8900_BASE); +#endif + return rc; +} +#endif diff --git a/u-boot/board/mpl/vcma9/vcma9.h b/u-boot/board/mpl/vcma9/vcma9.h new file mode 100644 index 0000000..94fd2fa --- /dev/null +++ b/u-boot/board/mpl/vcma9/vcma9.h @@ -0,0 +1,134 @@ +/* + * (C) Copyright 2002, 2003 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * 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 + * + */ + /**************************************************************************** + * Global routines used for VCMA9 + *****************************************************************************/ + +#include <asm/arch/s3c24x0_cpu.h> + +extern int mem_test(unsigned long start, unsigned long ramsize,int mode); + +void print_vcma9_info(void); + +#if defined(CONFIG_CMD_NAND) +typedef enum { + NFCE_LOW, + NFCE_HIGH +} NFCE_STATE; + +static inline void NF_Conf(u16 conf) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + nand->NFCONF = conf; +} + +static inline void NF_Cmd(u8 cmd) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + nand->NFCMD = cmd; +} + +static inline void NF_CmdW(u8 cmd) +{ + NF_Cmd(cmd); + udelay(1); +} + +static inline void NF_Addr(u8 addr) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + nand->NFADDR = addr; +} + +static inline void NF_SetCE(NFCE_STATE s) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + switch (s) { + case NFCE_LOW: + nand->NFCONF &= ~(1<<11); + break; + + case NFCE_HIGH: + nand->NFCONF |= (1<<11); + break; + } +} + +static inline void NF_WaitRB(void) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + while (!(nand->NFSTAT & (1<<0))); +} + +static inline void NF_Write(u8 data) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + nand->NFDATA = data; +} + +static inline u8 NF_Read(void) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + return(nand->NFDATA); +} + +static inline void NF_Init_ECC(void) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + nand->NFCONF |= (1<<12); +} + +static inline u32 NF_Read_ECC(void) +{ + struct s3c2410_nand * const nand = s3c2410_get_base_nand(); + + return(nand->NFECC); +} + +#endif + +/* VCMA9 PLD regsiters */ +typedef struct { + u8 ID; + u8 NIC; + u8 CAN; + u8 MISC; + u8 GPCD; + u8 BOARD; + u8 SDRAM; +} /*__attribute__((__packed__))*/ VCMA9_PLD; + +#define VCMA9_PLD_BASE 0x2C000100 +static inline VCMA9_PLD *VCMA9_get_base_PLD(void) +{ + return (VCMA9_PLD * const)VCMA9_PLD_BASE; +} |