diff options
author | H. Nikolaus Schaller <hns@goldelico.com> | 2012-03-26 20:55:28 +0200 |
---|---|---|
committer | H. Nikolaus Schaller <hns@goldelico.com> | 2012-03-26 20:55:28 +0200 |
commit | 92988a21ad4c4c9504295ccb580c9f806134471b (patch) | |
tree | 5effc9f14170112450de05c67dafbe8d5034d595 /arch/powerpc/cpu/ppc4xx | |
parent | ca2b506783b676c95762c54ea24dcfdaae1947c9 (diff) | |
download | bootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.zip bootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.tar.gz bootable_bootloader_goldelico_gta04-92988a21ad4c4c9504295ccb580c9f806134471b.tar.bz2 |
added boot script files to repository
Diffstat (limited to 'arch/powerpc/cpu/ppc4xx')
42 files changed, 0 insertions, 22385 deletions
diff --git a/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c b/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c deleted file mode 100644 index a31b17e..0000000 --- a/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c - * This SPD SDRAM detection code supports IBM/AMCC PPC44x cpu with a - * SDRAM controller. Those are all current 405 PPC's. - * - * (C) Copyright 2001 - * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com - * - * Based on code by: - * - * Kenneth Johansson ,Ericsson AB. - * kenneth.johansson@etx.ericsson.se - * - * hacked up by bill hunter. fixed so we could run before - * serial_init and console_init. previous version avoided this by - * running out of cache memory during serial/console init, then running - * this code later. - * - * (C) Copyright 2002 - * Jun Gu, Artesyn Technology, jung@artesyncp.com - * Support for AMCC 440 based on OpenBIOS draminit.c from IBM. - * - * (C) Copyright 2005 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/processor.h> -#include <i2c.h> -#include <asm/ppc4xx.h> - -#if defined(CONFIG_SPD_EEPROM) && !defined(CONFIG_440) - -/* - * Set default values - */ -#ifndef CONFIG_SYS_I2C_SPEED -#define CONFIG_SYS_I2C_SPEED 50000 -#endif - -#define ONE_BILLION 1000000000 - -#define SDRAM0_CFG_DCE 0x80000000 -#define SDRAM0_CFG_SRE 0x40000000 -#define SDRAM0_CFG_PME 0x20000000 -#define SDRAM0_CFG_MEMCHK 0x10000000 -#define SDRAM0_CFG_REGEN 0x08000000 -#define SDRAM0_CFG_ECCDD 0x00400000 -#define SDRAM0_CFG_EMDULR 0x00200000 -#define SDRAM0_CFG_DRW_SHIFT (31-6) -#define SDRAM0_CFG_BRPF_SHIFT (31-8) - -#define SDRAM0_TR_CASL_SHIFT (31-8) -#define SDRAM0_TR_PTA_SHIFT (31-13) -#define SDRAM0_TR_CTP_SHIFT (31-15) -#define SDRAM0_TR_LDF_SHIFT (31-17) -#define SDRAM0_TR_RFTA_SHIFT (31-29) -#define SDRAM0_TR_RCD_SHIFT (31-31) - -#define SDRAM0_RTR_SHIFT (31-15) -#define SDRAM0_ECCCFG_SHIFT (31-11) - -/* SDRAM0_CFG enable macro */ -#define SDRAM0_CFG_BRPF(x) ( ( x & 0x3)<< SDRAM0_CFG_BRPF_SHIFT ) - -#define SDRAM0_BXCR_SZ_MASK 0x000e0000 -#define SDRAM0_BXCR_AM_MASK 0x0000e000 - -#define SDRAM0_BXCR_SZ_SHIFT (31-14) -#define SDRAM0_BXCR_AM_SHIFT (31-18) - -#define SDRAM0_BXCR_SZ(x) ( (( x << SDRAM0_BXCR_SZ_SHIFT) & SDRAM0_BXCR_SZ_MASK) ) -#define SDRAM0_BXCR_AM(x) ( (( x << SDRAM0_BXCR_AM_SHIFT) & SDRAM0_BXCR_AM_MASK) ) - -#ifdef CONFIG_SPDDRAM_SILENT -# define SPD_ERR(x) do { return 0; } while (0) -#else -# define SPD_ERR(x) do { printf(x); return(0); } while (0) -#endif - -#define sdram_HZ_to_ns(hertz) (1000000000/(hertz)) - -/* function prototypes */ -int spd_read(uint addr); - - -/* - * This function is reading data from the DIMM module EEPROM over the SPD bus - * and uses that to program the sdram controller. - * - * This works on boards that has the same schematics that the AMCC walnut has. - * - * Input: null for default I2C spd functions or a pointer to a custom function - * returning spd_data. - */ - -long int spd_sdram(int(read_spd)(uint addr)) -{ - int tmp,row,col; - int total_size,bank_size,bank_code; - int ecc_on; - int mode; - int bank_cnt; - - int sdram0_pmit=0x07c00000; -#ifndef CONFIG_405EP /* not on PPC405EP */ - int sdram0_besr0 = -1; - int sdram0_besr1 = -1; - int sdram0_eccesr = -1; -#endif - int sdram0_ecccfg; - - int sdram0_rtr=0; - int sdram0_tr=0; - - int sdram0_b0cr; - int sdram0_b1cr; - int sdram0_b2cr; - int sdram0_b3cr; - - int sdram0_cfg=0; - - int t_rp; - int t_rcd; - int t_ras; - int t_rc; - int min_cas; - - PPC4xx_SYS_INFO sys_info; - unsigned long bus_period_x_10; - - /* - * get the board info - */ - get_sys_info(&sys_info); - bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10); - - if (read_spd == 0){ - read_spd=spd_read; - /* - * Make sure I2C controller is initialized - * before continuing. - */ - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - } - - /* Make shure we are using SDRAM */ - if (read_spd(2) != 0x04) { - SPD_ERR("SDRAM - non SDRAM memory module found\n"); - } - - /* ------------------------------------------------------------------ - * configure memory timing register - * - * data from DIMM: - * 27 IN Row Precharge Time ( t RP) - * 29 MIN RAS to CAS Delay ( t RCD) - * 127 Component and Clock Detail ,clk0-clk3, junction temp, CAS - * -------------------------------------------------------------------*/ - - /* - * first figure out which cas latency mode to use - * use the min supported mode - */ - - tmp = read_spd(127) & 0x6; - if (tmp == 0x02) { /* only cas = 2 supported */ - min_cas = 2; -/* t_ck = read_spd(9); */ -/* t_ac = read_spd(10); */ - } else if (tmp == 0x04) { /* only cas = 3 supported */ - min_cas = 3; -/* t_ck = read_spd(9); */ -/* t_ac = read_spd(10); */ - } else if (tmp == 0x06) { /* 2,3 supported, so use 2 */ - min_cas = 2; -/* t_ck = read_spd(23); */ -/* t_ac = read_spd(24); */ - } else { - SPD_ERR("SDRAM - unsupported CAS latency \n"); - } - - /* get some timing values, t_rp,t_rcd,t_ras,t_rc - */ - t_rp = read_spd(27); - t_rcd = read_spd(29); - t_ras = read_spd(30); - t_rc = t_ras + t_rp; - - /* The following timing calcs subtract 1 before deviding. - * this has effect of using ceiling instead of floor rounding, - * and also subtracting 1 to convert number to reg value - */ - /* set up CASL */ - sdram0_tr = (min_cas - 1) << SDRAM0_TR_CASL_SHIFT; - /* set up PTA */ - sdram0_tr |= ((((t_rp - 1) * 10)/bus_period_x_10) & 0x3) << SDRAM0_TR_PTA_SHIFT; - /* set up CTP */ - tmp = (((t_rc - t_rcd - t_rp -1) * 10) / bus_period_x_10) & 0x3; - if (tmp < 1) - tmp = 1; - sdram0_tr |= tmp << SDRAM0_TR_CTP_SHIFT; - /* set LDF = 2 cycles, reg value = 1 */ - sdram0_tr |= 1 << SDRAM0_TR_LDF_SHIFT; - /* set RFTA = t_rfc/bus_period, use t_rfc = t_rc */ - tmp = (((t_rc - 1) * 10) / bus_period_x_10) - 3; - if (tmp < 0) - tmp = 0; - if (tmp > 6) - tmp = 6; - sdram0_tr |= tmp << SDRAM0_TR_RFTA_SHIFT; - /* set RCD = t_rcd/bus_period*/ - sdram0_tr |= ((((t_rcd - 1) * 10) / bus_period_x_10) &0x3) << SDRAM0_TR_RCD_SHIFT ; - - - /*------------------------------------------------------------------ - * configure RTR register - * -------------------------------------------------------------------*/ - row = read_spd(3); - col = read_spd(4); - tmp = read_spd(12) & 0x7f ; /* refresh type less self refresh bit */ - switch (tmp) { - case 0x00: - tmp = 15625; - break; - case 0x01: - tmp = 15625 / 4; - break; - case 0x02: - tmp = 15625 / 2; - break; - case 0x03: - tmp = 15625 * 2; - break; - case 0x04: - tmp = 15625 * 4; - break; - case 0x05: - tmp = 15625 * 8; - break; - default: - SPD_ERR("SDRAM - Bad refresh period \n"); - } - /* convert from nsec to bus cycles */ - tmp = (tmp * 10) / bus_period_x_10; - sdram0_rtr = (tmp & 0x3ff8) << SDRAM0_RTR_SHIFT; - - /*------------------------------------------------------------------ - * determine the number of banks used - * -------------------------------------------------------------------*/ - /* byte 7:6 is module data width */ - if (read_spd(7) != 0) - SPD_ERR("SDRAM - unsupported module width\n"); - tmp = read_spd(6); - if (tmp < 32) - SPD_ERR("SDRAM - unsupported module width\n"); - else if (tmp < 64) - bank_cnt = 1; /* one bank per sdram side */ - else if (tmp < 73) - bank_cnt = 2; /* need two banks per side */ - else if (tmp < 161) - bank_cnt = 4; /* need four banks per side */ - else - SPD_ERR("SDRAM - unsupported module width\n"); - - /* byte 5 is the module row count (refered to as dimm "sides") */ - tmp = read_spd(5); - if (tmp == 1) - ; - else if (tmp==2) - bank_cnt *= 2; - else if (tmp==4) - bank_cnt *= 4; - else - bank_cnt = 8; /* 8 is an error code */ - - if (bank_cnt > 4) /* we only have 4 banks to work with */ - SPD_ERR("SDRAM - unsupported module rows for this width\n"); - - /* now check for ECC ability of module. We only support ECC - * on 32 bit wide devices with 8 bit ECC. - */ - if ((read_spd(11)==2) && (read_spd(6)==40) && (read_spd(14)==8)) { - sdram0_ecccfg = 0xf << SDRAM0_ECCCFG_SHIFT; - ecc_on = 1; - } else { - sdram0_ecccfg = 0; - ecc_on = 0; - } - - /*------------------------------------------------------------------ - * calculate total size - * -------------------------------------------------------------------*/ - /* calculate total size and do sanity check */ - tmp = read_spd(31); - total_size = 1 << 22; /* total_size = 4MB */ - /* now multiply 4M by the smallest device row density */ - /* note that we don't support asymetric rows */ - while (((tmp & 0x0001) == 0) && (tmp != 0)) { - total_size = total_size << 1; - tmp = tmp >> 1; - } - total_size *= read_spd(5); /* mult by module rows (dimm sides) */ - - /*------------------------------------------------------------------ - * map rows * cols * banks to a mode - * -------------------------------------------------------------------*/ - - switch (row) { - case 11: - switch (col) { - case 8: - mode=4; /* mode 5 */ - break; - case 9: - case 10: - mode=0; /* mode 1 */ - break; - default: - SPD_ERR("SDRAM - unsupported mode\n"); - } - break; - case 12: - switch (col) { - case 8: - mode=3; /* mode 4 */ - break; - case 9: - case 10: - mode=1; /* mode 2 */ - break; - default: - SPD_ERR("SDRAM - unsupported mode\n"); - } - break; - case 13: - switch (col) { - case 8: - mode=5; /* mode 6 */ - break; - case 9: - case 10: - if (read_spd(17) == 2) - mode = 6; /* mode 7 */ - else - mode = 2; /* mode 3 */ - break; - case 11: - mode = 2; /* mode 3 */ - break; - default: - SPD_ERR("SDRAM - unsupported mode\n"); - } - break; - default: - SPD_ERR("SDRAM - unsupported mode\n"); - } - - /*------------------------------------------------------------------ - * using the calculated values, compute the bank - * config register values. - * -------------------------------------------------------------------*/ - sdram0_b1cr = 0; - sdram0_b2cr = 0; - sdram0_b3cr = 0; - - /* compute the size of each bank */ - bank_size = total_size / bank_cnt; - /* convert bank size to bank size code for ppc4xx - by takeing log2(bank_size) - 22 */ - tmp = bank_size; /* start with tmp = bank_size */ - bank_code = 0; /* and bank_code = 0 */ - while (tmp > 1) { /* this takes log2 of tmp */ - bank_code++; /* and stores result in bank_code */ - tmp = tmp >> 1; - } /* bank_code is now log2(bank_size) */ - bank_code -= 22; /* subtract 22 to get the code */ - - tmp = SDRAM0_BXCR_SZ(bank_code) | SDRAM0_BXCR_AM(mode) | 1; - sdram0_b0cr = (bank_size * 0) | tmp; -#ifndef CONFIG_405EP /* not on PPC405EP */ - if (bank_cnt > 1) - sdram0_b2cr = (bank_size * 1) | tmp; - if (bank_cnt > 2) - sdram0_b1cr = (bank_size * 2) | tmp; - if (bank_cnt > 3) - sdram0_b3cr = (bank_size * 3) | tmp; -#else - /* PPC405EP chip only supports two SDRAM banks */ - if (bank_cnt > 1) - sdram0_b1cr = (bank_size * 1) | tmp; - if (bank_cnt > 2) - total_size = 2 * bank_size; -#endif - - /* - * enable sdram controller DCE=1 - * enable burst read prefetch to 32 bytes BRPF=2 - * leave other functions off - */ - - /*------------------------------------------------------------------ - * now that we've done our calculations, we are ready to - * program all the registers. - * -------------------------------------------------------------------*/ - - /* disable memcontroller so updates work */ - mtsdram(SDRAM0_CFG, 0); - -#ifndef CONFIG_405EP /* not on PPC405EP */ - mtsdram(SDRAM0_BESR0, sdram0_besr0); - mtsdram(SDRAM0_BESR1, sdram0_besr1); - mtsdram(SDRAM0_ECCCFG, sdram0_ecccfg); - mtsdram(SDRAM0_ECCESR, sdram0_eccesr); -#endif - mtsdram(SDRAM0_RTR, sdram0_rtr); - mtsdram(SDRAM0_PMIT, sdram0_pmit); - mtsdram(SDRAM0_B0CR, sdram0_b0cr); - mtsdram(SDRAM0_B1CR, sdram0_b1cr); -#ifndef CONFIG_405EP /* not on PPC405EP */ - mtsdram(SDRAM0_B2CR, sdram0_b2cr); - mtsdram(SDRAM0_B3CR, sdram0_b3cr); -#endif - mtsdram(SDRAM0_TR, sdram0_tr); - - /* SDRAM have a power on delay, 500 micro should do */ - udelay(500); - sdram0_cfg = SDRAM0_CFG_DCE | SDRAM0_CFG_BRPF(1) | SDRAM0_CFG_ECCDD | SDRAM0_CFG_EMDULR; - if (ecc_on) - sdram0_cfg |= SDRAM0_CFG_MEMCHK; - mtsdram(SDRAM0_CFG, sdram0_cfg); - - return (total_size); -} - -int spd_read(uint addr) -{ - uchar data[2]; - - if (i2c_read(SPD_EEPROM_ADDRESS, addr, 1, data, 1) == 0) - return (int)data[0]; - else - return 0; -} - -#endif /* CONFIG_SPD_EEPROM */ diff --git a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c deleted file mode 100644 index ec7291f..0000000 --- a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c +++ /dev/null @@ -1,1248 +0,0 @@ -/* - * arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c - * This SPD DDR detection code supports IBM/AMCC PPC44x cpu with a - * DDR controller. Those are 440GP/GX/EP/GR. - * - * (C) Copyright 2001 - * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com - * - * Based on code by: - * - * Kenneth Johansson ,Ericsson AB. - * kenneth.johansson@etx.ericsson.se - * - * hacked up by bill hunter. fixed so we could run before - * serial_init and console_init. previous version avoided this by - * running out of cache memory during serial/console init, then running - * this code later. - * - * (C) Copyright 2002 - * Jun Gu, Artesyn Technology, jung@artesyncp.com - * Support for AMCC 440 based on OpenBIOS draminit.c from IBM. - * - * (C) Copyright 2005-2007 - * Stefan Roese, DENX Software Engineering, sr@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 - */ - -/* define DEBUG for debugging output (obviously ;-)) */ -#if 0 -#define DEBUG -#endif - -#include <common.h> -#include <asm/processor.h> -#include <i2c.h> -#include <asm/ppc4xx.h> -#include <asm/mmu.h> - -#include "ecc.h" - -#if defined(CONFIG_SPD_EEPROM) && \ - (defined(CONFIG_440GP) || defined(CONFIG_440GX) || \ - defined(CONFIG_440EP) || defined(CONFIG_440GR)) - -/* - * Set default values - */ -#ifndef CONFIG_SYS_I2C_SPEED -#define CONFIG_SYS_I2C_SPEED 50000 -#endif - -#define ONE_BILLION 1000000000 - -/* - * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed - */ -void __spd_ddr_init_hang (void) -{ - hang (); -} -void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang"))); - -/*-----------------------------------------------------------------------------+ - | General Definition - +-----------------------------------------------------------------------------*/ -#define DEFAULT_SPD_ADDR1 0x53 -#define DEFAULT_SPD_ADDR2 0x52 -#define MAXBANKS 4 /* at most 4 dimm banks */ -#define MAX_SPD_BYTES 256 -#define NUMHALFCYCLES 4 -#define NUMMEMTESTS 8 -#define NUMMEMWORDS 8 -#define MAXBXCR 4 -#define TRUE 1 -#define FALSE 0 - -/* - * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory - * region. Right now the cache should still be disabled in U-Boot because of the - * EMAC driver, that need it's buffer descriptor to be located in non cached - * memory. - * - * If at some time this restriction doesn't apply anymore, just define - * CONFIG_4xx_DCACHE in the board config file and this code should setup - * everything correctly. - */ -#ifdef CONFIG_4xx_DCACHE -#define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */ -#else -#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */ -#endif - -/* bank_parms is used to sort the bank sizes by descending order */ -struct bank_param { - unsigned long cr; - unsigned long bank_size_bytes; -}; - -typedef struct bank_param BANKPARMS; - -#ifdef CONFIG_SYS_SIMULATE_SPD_EEPROM -extern const unsigned char cfg_simulate_spd_eeprom[128]; -#endif - -static unsigned char spd_read(uchar chip, uint addr); -static void get_spd_info(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void check_mem_type(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void check_volt_type(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_cfg0(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_cfg1(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_rtr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_tr0(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_tr1(void); - -static unsigned long program_bxcr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); - -/* - * This function is reading data from the DIMM module EEPROM over the SPD bus - * and uses that to program the sdram controller. - * - * This works on boards that has the same schematics that the AMCC walnut has. - * - * BUG: Don't handle ECC memory - * BUG: A few values in the TR register is currently hardcoded - */ -long int spd_sdram(void) { - unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; - unsigned long dimm_populated[sizeof(iic0_dimm_addr)]; - unsigned long total_size; - unsigned long cfg0; - unsigned long mcsts; - unsigned long num_dimm_banks; /* on board dimm banks */ - - num_dimm_banks = sizeof(iic0_dimm_addr); - - /* - * Make sure I2C controller is initialized - * before continuing. - */ - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - - /* - * Read the SPD information using I2C interface. Check to see if the - * DIMM slots are populated. - */ - get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /* - * Check the memory type for the dimms plugged. - */ - check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /* - * Check the voltage type for the dimms plugged. - */ - check_volt_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); - -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) - /* - * Soft-reset SDRAM controller. - */ - mtsdr(SDR0_SRST, SDR0_SRST_DMC); - mtsdr(SDR0_SRST, 0x00000000); -#endif - - /* - * program 440GP SDRAM controller options (SDRAM0_CFG0) - */ - program_cfg0(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /* - * program 440GP SDRAM controller options (SDRAM0_CFG1) - */ - program_cfg1(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /* - * program SDRAM refresh register (SDRAM0_RTR) - */ - program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /* - * program SDRAM Timing Register 0 (SDRAM0_TR0) - */ - program_tr0(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /* - * program the BxCR registers to find out total sdram installed - */ - total_size = program_bxcr(dimm_populated, iic0_dimm_addr, - num_dimm_banks); - -#ifdef CONFIG_PROG_SDRAM_TLB /* this define should eventually be removed */ - /* and program tlb entries for this size (dynamic) */ - program_tlb(0, 0, total_size, MY_TLB_WORD2_I_ENABLE); -#endif - - /* - * program SDRAM Clock Timing Register (SDRAM0_CLKTR) - */ - mtsdram(SDRAM0_CLKTR, 0x40000000); - - /* - * delay to ensure 200 usec has elapsed - */ - udelay(400); - - /* - * enable the memory controller - */ - mfsdram(SDRAM0_CFG0, cfg0); - mtsdram(SDRAM0_CFG0, cfg0 | SDRAM_CFG0_DCEN); - - /* - * wait for SDRAM_CFG0_DC_EN to complete - */ - while (1) { - mfsdram(SDRAM0_MCSTS, mcsts); - if ((mcsts & SDRAM_MCSTS_MRSC) != 0) - break; - } - - /* - * program SDRAM Timing Register 1, adding some delays - */ - program_tr1(); - -#ifdef CONFIG_DDR_ECC - /* - * If ecc is enabled, initialize the parity bits. - */ - ecc_init(CONFIG_SYS_SDRAM_BASE, total_size); -#endif - - return total_size; -} - -static unsigned char spd_read(uchar chip, uint addr) -{ - unsigned char data[2]; - -#ifdef CONFIG_SYS_SIMULATE_SPD_EEPROM - if (chip == CONFIG_SYS_SIMULATE_SPD_EEPROM) { - /* - * Onboard spd eeprom requested -> simulate values - */ - return cfg_simulate_spd_eeprom[addr]; - } -#endif /* CONFIG_SYS_SIMULATE_SPD_EEPROM */ - - if (i2c_probe(chip) == 0) { - if (i2c_read(chip, addr, 1, data, 1) == 0) { - return data[0]; - } - } - - return 0; -} - -static void get_spd_info(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long dimm_found; - unsigned char num_of_bytes; - unsigned char total_size; - - dimm_found = FALSE; - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - num_of_bytes = 0; - total_size = 0; - - num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0); - total_size = spd_read(iic0_dimm_addr[dimm_num], 1); - - if ((num_of_bytes != 0) && (total_size != 0)) { - dimm_populated[dimm_num] = TRUE; - dimm_found = TRUE; - debug("DIMM slot %lu: populated\n", dimm_num); - } else { - dimm_populated[dimm_num] = FALSE; - debug("DIMM slot %lu: Not populated\n", dimm_num); - } - } - - if (dimm_found == FALSE) { - printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n"); - spd_ddr_init_hang (); - } -} - -static void check_mem_type(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned char dimm_type; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] == TRUE) { - dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2); - switch (dimm_type) { - case 7: - debug("DIMM slot %lu: DDR SDRAM detected\n", dimm_num); - break; - default: - printf("ERROR: Unsupported DIMM detected in slot %lu.\n", - dimm_num); - printf("Only DDR SDRAM DIMMs are supported.\n"); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - } - } - } -} - -static void check_volt_type(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long voltage_type; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] == TRUE) { - voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8); - if (voltage_type != 0x04) { - printf("ERROR: DIMM %lu with unsupported voltage level.\n", - dimm_num); - spd_ddr_init_hang (); - } else { - debug("DIMM %lu voltage level supported.\n", dimm_num); - } - break; - } - } -} - -static void program_cfg0(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long cfg0; - unsigned long ecc_enabled; - unsigned char ecc; - unsigned char attributes; - unsigned long data_width; - unsigned long dimm_32bit; - unsigned long dimm_64bit; - - /* - * get Memory Controller Options 0 data - */ - mfsdram(SDRAM0_CFG0, cfg0); - - /* - * clear bits - */ - cfg0 &= ~(SDRAM_CFG0_DCEN | SDRAM_CFG0_MCHK_MASK | - SDRAM_CFG0_RDEN | SDRAM_CFG0_PMUD | - SDRAM_CFG0_DMWD_MASK | - SDRAM_CFG0_UIOS_MASK | SDRAM_CFG0_PDP); - - - /* - * FIXME: assume the DDR SDRAMs in both banks are the same - */ - ecc_enabled = TRUE; - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] == TRUE) { - ecc = spd_read(iic0_dimm_addr[dimm_num], 11); - if (ecc != 0x02) { - ecc_enabled = FALSE; - } - - /* - * program Registered DIMM Enable - */ - attributes = spd_read(iic0_dimm_addr[dimm_num], 21); - if ((attributes & 0x02) != 0x00) { - cfg0 |= SDRAM_CFG0_RDEN; - } - - /* - * program DDR SDRAM Data Width - */ - data_width = - (unsigned long)spd_read(iic0_dimm_addr[dimm_num],6) + - (((unsigned long)spd_read(iic0_dimm_addr[dimm_num],7)) << 8); - if (data_width == 64 || data_width == 72) { - dimm_64bit = TRUE; - cfg0 |= SDRAM_CFG0_DMWD_64; - } else if (data_width == 32 || data_width == 40) { - dimm_32bit = TRUE; - cfg0 |= SDRAM_CFG0_DMWD_32; - } else { - printf("WARNING: DIMM with datawidth of %lu bits.\n", - data_width); - printf("Only DIMMs with 32 or 64 bit datawidths supported.\n"); - spd_ddr_init_hang (); - } - break; - } - } - - /* - * program Memory Data Error Checking - */ - if (ecc_enabled == TRUE) { - cfg0 |= SDRAM_CFG0_MCHK_GEN; - } else { - cfg0 |= SDRAM_CFG0_MCHK_NON; - } - - /* - * program Page Management Unit (0 == enabled) - */ - cfg0 &= ~SDRAM_CFG0_PMUD; - - /* - * program Memory Controller Options 0 - * Note: DCEN must be enabled after all DDR SDRAM controller - * configuration registers get initialized. - */ - mtsdram(SDRAM0_CFG0, cfg0); -} - -static void program_cfg1(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long cfg1; - mfsdram(SDRAM0_CFG1, cfg1); - - /* - * Self-refresh exit, disable PM - */ - cfg1 &= ~(SDRAM_CFG1_SRE | SDRAM_CFG1_PMEN); - - /* - * program Memory Controller Options 1 - */ - mtsdram(SDRAM0_CFG1, cfg1); -} - -static void program_rtr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long bus_period_x_10; - unsigned long refresh_rate = 0; - unsigned char refresh_rate_type; - unsigned long refresh_interval; - unsigned long sdram_rtr; - PPC4xx_SYS_INFO sys_info; - - /* - * get the board info - */ - get_sys_info(&sys_info); - bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10); - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] == TRUE) { - refresh_rate_type = 0x7F & spd_read(iic0_dimm_addr[dimm_num], 12); - switch (refresh_rate_type) { - case 0x00: - refresh_rate = 15625; - break; - case 0x01: - refresh_rate = 15625/4; - break; - case 0x02: - refresh_rate = 15625/2; - break; - case 0x03: - refresh_rate = 15626*2; - break; - case 0x04: - refresh_rate = 15625*4; - break; - case 0x05: - refresh_rate = 15625*8; - break; - default: - printf("ERROR: DIMM %lu, unsupported refresh rate/type.\n", - dimm_num); - printf("Replace the DIMM module with a supported DIMM.\n"); - break; - } - - break; - } - } - - refresh_interval = refresh_rate * 10 / bus_period_x_10; - sdram_rtr = (refresh_interval & 0x3ff8) << 16; - - /* - * program Refresh Timer Register (SDRAM0_RTR) - */ - mtsdram(SDRAM0_RTR, sdram_rtr); -} - -static void program_tr0(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long tr0; - unsigned char wcsbc; - unsigned char t_rp_ns; - unsigned char t_rcd_ns; - unsigned char t_ras_ns; - unsigned long t_rp_clk; - unsigned long t_ras_rcd_clk; - unsigned long t_rcd_clk; - unsigned long t_rfc_clk; - unsigned long plb_check; - unsigned char cas_bit; - unsigned long cas_index; - unsigned char cas_2_0_available; - unsigned char cas_2_5_available; - unsigned char cas_3_0_available; - unsigned long cycle_time_ns_x_10[3]; - unsigned long tcyc_3_0_ns_x_10; - unsigned long tcyc_2_5_ns_x_10; - unsigned long tcyc_2_0_ns_x_10; - unsigned long tcyc_reg; - unsigned long bus_period_x_10; - PPC4xx_SYS_INFO sys_info; - unsigned long residue; - - /* - * get the board info - */ - get_sys_info(&sys_info); - bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10); - - /* - * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits - */ - mfsdram(SDRAM0_TR0, tr0); - tr0 &= ~(SDRAM_TR0_SDWR_MASK | SDRAM_TR0_SDWD_MASK | - SDRAM_TR0_SDCL_MASK | SDRAM_TR0_SDPA_MASK | - SDRAM_TR0_SDCP_MASK | SDRAM_TR0_SDLD_MASK | - SDRAM_TR0_SDRA_MASK | SDRAM_TR0_SDRD_MASK); - - /* - * initialization - */ - wcsbc = 0; - t_rp_ns = 0; - t_rcd_ns = 0; - t_ras_ns = 0; - cas_2_0_available = TRUE; - cas_2_5_available = TRUE; - cas_3_0_available = TRUE; - tcyc_2_0_ns_x_10 = 0; - tcyc_2_5_ns_x_10 = 0; - tcyc_3_0_ns_x_10 = 0; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] == TRUE) { - wcsbc = spd_read(iic0_dimm_addr[dimm_num], 15); - t_rp_ns = spd_read(iic0_dimm_addr[dimm_num], 27) >> 2; - t_rcd_ns = spd_read(iic0_dimm_addr[dimm_num], 29) >> 2; - t_ras_ns = spd_read(iic0_dimm_addr[dimm_num], 30); - cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18); - - for (cas_index = 0; cas_index < 3; cas_index++) { - switch (cas_index) { - case 0: - tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9); - break; - case 1: - tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23); - break; - default: - tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25); - break; - } - - if ((tcyc_reg & 0x0F) >= 10) { - printf("ERROR: Tcyc incorrect for DIMM in slot %lu\n", - dimm_num); - spd_ddr_init_hang (); - } - - cycle_time_ns_x_10[cas_index] = - (((tcyc_reg & 0xF0) >> 4) * 10) + (tcyc_reg & 0x0F); - } - - cas_index = 0; - - if ((cas_bit & 0x80) != 0) { - cas_index += 3; - } else if ((cas_bit & 0x40) != 0) { - cas_index += 2; - } else if ((cas_bit & 0x20) != 0) { - cas_index += 1; - } - - if (((cas_bit & 0x10) != 0) && (cas_index < 3)) { - tcyc_3_0_ns_x_10 = cycle_time_ns_x_10[cas_index]; - cas_index++; - } else { - if (cas_index != 0) { - cas_index++; - } - cas_3_0_available = FALSE; - } - - if (((cas_bit & 0x08) != 0) || (cas_index < 3)) { - tcyc_2_5_ns_x_10 = cycle_time_ns_x_10[cas_index]; - cas_index++; - } else { - if (cas_index != 0) { - cas_index++; - } - cas_2_5_available = FALSE; - } - - if (((cas_bit & 0x04) != 0) || (cas_index < 3)) { - tcyc_2_0_ns_x_10 = cycle_time_ns_x_10[cas_index]; - cas_index++; - } else { - if (cas_index != 0) { - cas_index++; - } - cas_2_0_available = FALSE; - } - - break; - } - } - - /* - * Program SD_WR and SD_WCSBC fields - */ - tr0 |= SDRAM_TR0_SDWR_2_CLK; /* Write Recovery: 2 CLK */ - switch (wcsbc) { - case 0: - tr0 |= SDRAM_TR0_SDWD_0_CLK; - break; - default: - tr0 |= SDRAM_TR0_SDWD_1_CLK; - break; - } - - /* - * Program SD_CASL field - */ - if ((cas_2_0_available == TRUE) && - (bus_period_x_10 >= tcyc_2_0_ns_x_10)) { - tr0 |= SDRAM_TR0_SDCL_2_0_CLK; - } else if ((cas_2_5_available == TRUE) && - (bus_period_x_10 >= tcyc_2_5_ns_x_10)) { - tr0 |= SDRAM_TR0_SDCL_2_5_CLK; - } else if ((cas_3_0_available == TRUE) && - (bus_period_x_10 >= tcyc_3_0_ns_x_10)) { - tr0 |= SDRAM_TR0_SDCL_3_0_CLK; - } else { - printf("ERROR: No supported CAS latency with the installed DIMMs.\n"); - printf("Only CAS latencies of 2.0, 2.5, and 3.0 are supported.\n"); - printf("Make sure the PLB speed is within the supported range.\n"); - spd_ddr_init_hang (); - } - - /* - * Calculate Trp in clock cycles and round up if necessary - * Program SD_PTA field - */ - t_rp_clk = sys_info.freqPLB * t_rp_ns / ONE_BILLION; - plb_check = ONE_BILLION * t_rp_clk / t_rp_ns; - if (sys_info.freqPLB != plb_check) { - t_rp_clk++; - } - switch ((unsigned long)t_rp_clk) { - case 0: - case 1: - case 2: - tr0 |= SDRAM_TR0_SDPA_2_CLK; - break; - case 3: - tr0 |= SDRAM_TR0_SDPA_3_CLK; - break; - default: - tr0 |= SDRAM_TR0_SDPA_4_CLK; - break; - } - - /* - * Program SD_CTP field - */ - t_ras_rcd_clk = sys_info.freqPLB * (t_ras_ns - t_rcd_ns) / ONE_BILLION; - plb_check = ONE_BILLION * t_ras_rcd_clk / (t_ras_ns - t_rcd_ns); - if (sys_info.freqPLB != plb_check) { - t_ras_rcd_clk++; - } - switch (t_ras_rcd_clk) { - case 0: - case 1: - case 2: - tr0 |= SDRAM_TR0_SDCP_2_CLK; - break; - case 3: - tr0 |= SDRAM_TR0_SDCP_3_CLK; - break; - case 4: - tr0 |= SDRAM_TR0_SDCP_4_CLK; - break; - default: - tr0 |= SDRAM_TR0_SDCP_5_CLK; - break; - } - - /* - * Program SD_LDF field - */ - tr0 |= SDRAM_TR0_SDLD_2_CLK; - - /* - * Program SD_RFTA field - * FIXME tRFC hardcoded as 75 nanoseconds - */ - t_rfc_clk = sys_info.freqPLB / (ONE_BILLION / 75); - residue = sys_info.freqPLB % (ONE_BILLION / 75); - if (residue >= (ONE_BILLION / 150)) { - t_rfc_clk++; - } - switch (t_rfc_clk) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - tr0 |= SDRAM_TR0_SDRA_6_CLK; - break; - case 7: - tr0 |= SDRAM_TR0_SDRA_7_CLK; - break; - case 8: - tr0 |= SDRAM_TR0_SDRA_8_CLK; - break; - case 9: - tr0 |= SDRAM_TR0_SDRA_9_CLK; - break; - case 10: - tr0 |= SDRAM_TR0_SDRA_10_CLK; - break; - case 11: - tr0 |= SDRAM_TR0_SDRA_11_CLK; - break; - case 12: - tr0 |= SDRAM_TR0_SDRA_12_CLK; - break; - default: - tr0 |= SDRAM_TR0_SDRA_13_CLK; - break; - } - - /* - * Program SD_RCD field - */ - t_rcd_clk = sys_info.freqPLB * t_rcd_ns / ONE_BILLION; - plb_check = ONE_BILLION * t_rcd_clk / t_rcd_ns; - if (sys_info.freqPLB != plb_check) { - t_rcd_clk++; - } - switch (t_rcd_clk) { - case 0: - case 1: - case 2: - tr0 |= SDRAM_TR0_SDRD_2_CLK; - break; - case 3: - tr0 |= SDRAM_TR0_SDRD_3_CLK; - break; - default: - tr0 |= SDRAM_TR0_SDRD_4_CLK; - break; - } - - debug("tr0: %x\n", tr0); - mtsdram(SDRAM0_TR0, tr0); -} - -static int short_mem_test(void) -{ - unsigned long i, j; - unsigned long bxcr_num; - unsigned long *membase; - const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = { - {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, - {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}, - {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555}, - {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA}, - {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A}, - {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5}, - {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA}, - {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55}}; - - for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) { - mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (bxcr_num << 2)); - if ((mfdcr(SDRAM0_CFGDATA) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) { - /* Bank is enabled */ - membase = (unsigned long*) - (mfdcr(SDRAM0_CFGDATA) & SDRAM_BXCR_SDBA_MASK); - - /* - * Run the short memory test - */ - for (i = 0; i < NUMMEMTESTS; i++) { - for (j = 0; j < NUMMEMWORDS; j++) { - /* printf("bank enabled base:%x\n", &membase[j]); */ - membase[j] = test[i][j]; - ppcDcbf((unsigned long)&(membase[j])); - } - - for (j = 0; j < NUMMEMWORDS; j++) { - if (membase[j] != test[i][j]) { - ppcDcbf((unsigned long)&(membase[j])); - return 0; - } - ppcDcbf((unsigned long)&(membase[j])); - } - - if (j < NUMMEMWORDS) - return 0; - } - - /* - * see if the rdclt value passed - */ - if (i < NUMMEMTESTS) - return 0; - } - } - - return 1; -} - -static void program_tr1(void) -{ - unsigned long tr0; - unsigned long tr1; - unsigned long cfg0; - unsigned long ecc_temp; - unsigned long dlycal; - unsigned long dly_val; - unsigned long k; - unsigned long max_pass_length; - unsigned long current_pass_length; - unsigned long current_fail_length; - unsigned long current_start; - unsigned long rdclt; - unsigned long rdclt_offset; - long max_start; - long max_end; - long rdclt_average; - unsigned char window_found; - unsigned char fail_found; - unsigned char pass_found; - PPC4xx_SYS_INFO sys_info; - - /* - * get the board info - */ - get_sys_info(&sys_info); - - /* - * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits - */ - mfsdram(SDRAM0_TR1, tr1); - tr1 &= ~(SDRAM_TR1_RDSS_MASK | SDRAM_TR1_RDSL_MASK | - SDRAM_TR1_RDCD_MASK | SDRAM_TR1_RDCT_MASK); - - mfsdram(SDRAM0_TR0, tr0); - if (((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) && - (sys_info.freqPLB > 100000000)) { - tr1 |= SDRAM_TR1_RDSS_TR2; - tr1 |= SDRAM_TR1_RDSL_STAGE3; - tr1 |= SDRAM_TR1_RDCD_RCD_1_2; - } else { - tr1 |= SDRAM_TR1_RDSS_TR1; - tr1 |= SDRAM_TR1_RDSL_STAGE2; - tr1 |= SDRAM_TR1_RDCD_RCD_0_0; - } - - /* - * save CFG0 ECC setting to a temporary variable and turn ECC off - */ - mfsdram(SDRAM0_CFG0, cfg0); - ecc_temp = cfg0 & SDRAM_CFG0_MCHK_MASK; - mtsdram(SDRAM0_CFG0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_NON); - - /* - * get the delay line calibration register value - */ - mfsdram(SDRAM0_DLYCAL, dlycal); - dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2; - - max_pass_length = 0; - max_start = 0; - max_end = 0; - current_pass_length = 0; - current_fail_length = 0; - current_start = 0; - rdclt_offset = 0; - window_found = FALSE; - fail_found = FALSE; - pass_found = FALSE; - debug("Starting memory test "); - - for (k = 0; k < NUMHALFCYCLES; k++) { - for (rdclt = 0; rdclt < dly_val; rdclt++) { - /* - * Set the timing reg for the test. - */ - mtsdram(SDRAM0_TR1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt))); - - if (short_mem_test()) { - if (fail_found == TRUE) { - pass_found = TRUE; - if (current_pass_length == 0) { - current_start = rdclt_offset + rdclt; - } - - current_fail_length = 0; - current_pass_length++; - - if (current_pass_length > max_pass_length) { - max_pass_length = current_pass_length; - max_start = current_start; - max_end = rdclt_offset + rdclt; - } - } - } else { - current_pass_length = 0; - current_fail_length++; - - if (current_fail_length >= (dly_val>>2)) { - if (fail_found == FALSE) { - fail_found = TRUE; - } else if (pass_found == TRUE) { - window_found = TRUE; - break; - } - } - } - } - debug("."); - - if (window_found == TRUE) { - break; - } - - tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK; - rdclt_offset += dly_val; - } - debug("\n"); - - /* - * make sure we find the window - */ - if (window_found == FALSE) { - printf("ERROR: Cannot determine a common read delay.\n"); - spd_ddr_init_hang (); - } - - /* - * restore the orignal ECC setting - */ - mtsdram(SDRAM0_CFG0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | ecc_temp); - - /* - * set the SDRAM TR1 RDCD value - */ - tr1 &= ~SDRAM_TR1_RDCD_MASK; - if ((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) { - tr1 |= SDRAM_TR1_RDCD_RCD_1_2; - } else { - tr1 |= SDRAM_TR1_RDCD_RCD_0_0; - } - - /* - * set the SDRAM TR1 RDCLT value - */ - tr1 &= ~SDRAM_TR1_RDCT_MASK; - while (max_end >= (dly_val << 1)) { - max_end -= (dly_val << 1); - max_start -= (dly_val << 1); - } - - rdclt_average = ((max_start + max_end) >> 1); - - if (rdclt_average < 0) { - rdclt_average = 0; - } - - if (rdclt_average >= dly_val) { - rdclt_average -= dly_val; - tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK; - } - tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average); - - debug("tr1: %x\n", tr1); - - /* - * program SDRAM Timing Register 1 TR1 - */ - mtsdram(SDRAM0_TR1, tr1); -} - -static unsigned long program_bxcr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long bank_base_addr; - unsigned long cr; - unsigned long i; - unsigned long j; - unsigned long temp; - unsigned char num_row_addr; - unsigned char num_col_addr; - unsigned char num_banks; - unsigned char bank_size_id; - unsigned long ctrl_bank_num[MAXBANKS]; - unsigned long bx_cr_num; - unsigned long largest_size_index; - unsigned long largest_size; - unsigned long current_size_index; - BANKPARMS bank_parms[MAXBXCR]; - unsigned long sorted_bank_num[MAXBXCR]; /* DDR Controller bank number table (sorted by size) */ - unsigned long sorted_bank_size[MAXBXCR]; /* DDR Controller bank size table (sorted by size)*/ - - /* - * Set the BxCR regs. First, wipe out the bank config registers. - */ - for (bx_cr_num = 0; bx_cr_num < MAXBXCR; bx_cr_num++) { - mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (bx_cr_num << 2)); - mtdcr(SDRAM0_CFGDATA, 0x00000000); - bank_parms[bx_cr_num].bank_size_bytes = 0; - } - -#ifdef CONFIG_BAMBOO - /* - * This next section is hardware dependent and must be programmed - * to match the hardware. For bamboo, the following holds... - * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0 (soldered onboard) - * 2. SDRAM0_B1CR: Bank 0 of dimm 1 ctrl_bank_num : 1 - * 3. SDRAM0_B2CR: Bank 1 of dimm 1 ctrl_bank_num : 1 - * 4. SDRAM0_B3CR: Bank 0 of dimm 2 ctrl_bank_num : 3 - * ctrl_bank_num corresponds to the first usable DDR controller bank number by DIMM - */ - ctrl_bank_num[0] = 0; - ctrl_bank_num[1] = 1; - ctrl_bank_num[2] = 3; -#else - /* - * Ocotea, Ebony and the other IBM/AMCC eval boards have - * 2 DIMM slots with each max 2 banks - */ - ctrl_bank_num[0] = 0; - ctrl_bank_num[1] = 2; -#endif - - /* - * reset the bank_base address - */ - bank_base_addr = CONFIG_SYS_SDRAM_BASE; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] == TRUE) { - num_row_addr = spd_read(iic0_dimm_addr[dimm_num], 3); - num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4); - num_banks = spd_read(iic0_dimm_addr[dimm_num], 5); - bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31); - debug("DIMM%d: row=%d col=%d banks=%d\n", dimm_num, - num_row_addr, num_col_addr, num_banks); - - /* - * Set the SDRAM0_BxCR regs - */ - cr = 0; - switch (bank_size_id) { - case 0x02: - cr |= SDRAM_BXCR_SDSZ_8; - break; - case 0x04: - cr |= SDRAM_BXCR_SDSZ_16; - break; - case 0x08: - cr |= SDRAM_BXCR_SDSZ_32; - break; - case 0x10: - cr |= SDRAM_BXCR_SDSZ_64; - break; - case 0x20: - cr |= SDRAM_BXCR_SDSZ_128; - break; - case 0x40: - cr |= SDRAM_BXCR_SDSZ_256; - break; - case 0x80: - cr |= SDRAM_BXCR_SDSZ_512; - break; - default: - printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n", - dimm_num); - printf("ERROR: Unsupported value for the banksize: %d.\n", - bank_size_id); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - } - - switch (num_col_addr) { - case 0x08: - cr |= SDRAM_BXCR_SDAM_1; - break; - case 0x09: - cr |= SDRAM_BXCR_SDAM_2; - break; - case 0x0A: - cr |= SDRAM_BXCR_SDAM_3; - break; - case 0x0B: - cr |= SDRAM_BXCR_SDAM_4; - break; - default: - printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n", - dimm_num); - printf("ERROR: Unsupported value for number of " - "column addresses: %d.\n", num_col_addr); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - } - - /* - * enable the bank - */ - cr |= SDRAM_BXCR_SDBE; - - for (i = 0; i < num_banks; i++) { - bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes = - (4 << 20) * bank_size_id; - bank_parms[ctrl_bank_num[dimm_num]+i].cr = cr; - debug("DIMM%d-bank %d (SDRAM0_B%dCR): bank_size_bytes=%d\n", - dimm_num, i, ctrl_bank_num[dimm_num]+i, - bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes); - } - } - } - - /* Initialize sort tables */ - for (i = 0; i < MAXBXCR; i++) { - sorted_bank_num[i] = i; - sorted_bank_size[i] = bank_parms[i].bank_size_bytes; - } - - for (i = 0; i < MAXBXCR-1; i++) { - largest_size = sorted_bank_size[i]; - largest_size_index = 255; - - /* Find the largest remaining value */ - for (j = i + 1; j < MAXBXCR; j++) { - if (sorted_bank_size[j] > largest_size) { - /* Save largest remaining value and its index */ - largest_size = sorted_bank_size[j]; - largest_size_index = j; - } - } - - if (largest_size_index != 255) { - /* Swap the current and largest values */ - current_size_index = sorted_bank_num[largest_size_index]; - sorted_bank_size[largest_size_index] = sorted_bank_size[i]; - sorted_bank_size[i] = largest_size; - sorted_bank_num[largest_size_index] = sorted_bank_num[i]; - sorted_bank_num[i] = current_size_index; - } - } - - /* Set the SDRAM0_BxCR regs thanks to sort tables */ - for (bx_cr_num = 0, bank_base_addr = 0; bx_cr_num < MAXBXCR; bx_cr_num++) { - if (bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes) { - mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (sorted_bank_num[bx_cr_num] << 2)); - temp = mfdcr(SDRAM0_CFGDATA) & ~(SDRAM_BXCR_SDBA_MASK | SDRAM_BXCR_SDSZ_MASK | - SDRAM_BXCR_SDAM_MASK | SDRAM_BXCR_SDBE); - temp = temp | (bank_base_addr & SDRAM_BXCR_SDBA_MASK) | - bank_parms[sorted_bank_num[bx_cr_num]].cr; - mtdcr(SDRAM0_CFGDATA, temp); - bank_base_addr += bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes; - debug("SDRAM0_B%dCR=0x%08lx\n", sorted_bank_num[bx_cr_num], temp); - } - } - - return(bank_base_addr); -} -#endif /* CONFIG_SPD_EEPROM */ diff --git a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c deleted file mode 100644 index 95df1d9..0000000 --- a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c +++ /dev/null @@ -1,3193 +0,0 @@ -/* - * arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c - * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a - * DDR2 controller (non Denali Core). Those currently are: - * - * 405: 405EX(r) - * 440/460: 440SP/440SPe/460EX/460GT - * - * Copyright (c) 2008 Nuovation System Designs, LLC - * Grant Erickson <gerickson@nuovations.com> - - * (C) Copyright 2007-2009 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * COPYRIGHT AMCC CORPORATION 2004 - * - * 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 - * - */ - -/* define DEBUG for debugging output (obviously ;-)) */ -#if 0 -#define DEBUG -#endif - -#include <common.h> -#include <command.h> -#include <asm/ppc4xx.h> -#include <i2c.h> -#include <asm/io.h> -#include <asm/processor.h> -#include <asm/mmu.h> -#include <asm/cache.h> - -#include "ecc.h" - -#define PPC4xx_IBM_DDR2_DUMP_REGISTER(mnemonic) \ - do { \ - u32 data; \ - mfsdram(SDRAM_##mnemonic, data); \ - printf("%20s[%02x] = 0x%08X\n", \ - "SDRAM_" #mnemonic, SDRAM_##mnemonic, data); \ - } while (0) - -#define PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(mnemonic) \ - do { \ - u32 data; \ - data = mfdcr(SDRAM_##mnemonic); \ - printf("%20s[%02x] = 0x%08X\n", \ - "SDRAM_" #mnemonic, SDRAM_##mnemonic, data); \ - } while (0) - -#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) -static void update_rdcc(void) -{ - u32 val; - - /* - * Complete RDSS configuration as mentioned on page 7 of the AMCC - * PowerPC440SP/SPe DDR2 application note: - * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning" - * - * Or item #10 "10. Complete RDSS configuration" in chapter - * "22.2.9 SDRAM Initialization" of AMCC PPC460EX/EXr/GT users - * manual. - */ - mfsdram(SDRAM_RTSR, val); - if ((val & SDRAM_RTSR_TRK1SM_MASK) == SDRAM_RTSR_TRK1SM_ATPLS1) { - mfsdram(SDRAM_RDCC, val); - if ((val & SDRAM_RDCC_RDSS_MASK) != SDRAM_RDCC_RDSS_T4) { - val += 0x40000000; - mtsdram(SDRAM_RDCC, val); - } - } -} -#endif - -#if defined(CONFIG_440) -/* - * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 - * memory region. Right now the cache should still be disabled in U-Boot - * because of the EMAC driver, that need its buffer descriptor to be located - * in non cached memory. - * - * If at some time this restriction doesn't apply anymore, just define - * CONFIG_4xx_DCACHE in the board config file and this code should setup - * everything correctly. - */ -#ifdef CONFIG_4xx_DCACHE -/* enable caching on SDRAM */ -#define MY_TLB_WORD2_I_ENABLE 0 -#else -/* disable caching on SDRAM */ -#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE -#endif /* CONFIG_4xx_DCACHE */ - -void dcbz_area(u32 start_address, u32 num_bytes); -#endif /* CONFIG_440 */ - -#define MAXRANKS 4 -#define MAXBXCF 4 - -#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d)) - -#if !defined(CONFIG_NAND_SPL) -/*-----------------------------------------------------------------------------+ - * sdram_memsize - *-----------------------------------------------------------------------------*/ -phys_size_t sdram_memsize(void) -{ - phys_size_t mem_size; - unsigned long mcopt2; - unsigned long mcstat; - unsigned long mb0cf; - unsigned long sdsz; - unsigned long i; - - mem_size = 0; - - mfsdram(SDRAM_MCOPT2, mcopt2); - mfsdram(SDRAM_MCSTAT, mcstat); - - /* DDR controller must be enabled and not in self-refresh. */ - /* Otherwise memsize is zero. */ - if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE) - && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT) - && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK)) - == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) { - for (i = 0; i < MAXBXCF; i++) { - mfsdram(SDRAM_MB0CF + (i << 2), mb0cf); - /* Banks enabled */ - if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) { -#if defined(CONFIG_440) - sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK; -#else - sdsz = mb0cf & SDRAM_RXBAS_SDSZ_MASK; -#endif - switch(sdsz) { - case SDRAM_RXBAS_SDSZ_8: - mem_size+=8; - break; - case SDRAM_RXBAS_SDSZ_16: - mem_size+=16; - break; - case SDRAM_RXBAS_SDSZ_32: - mem_size+=32; - break; - case SDRAM_RXBAS_SDSZ_64: - mem_size+=64; - break; - case SDRAM_RXBAS_SDSZ_128: - mem_size+=128; - break; - case SDRAM_RXBAS_SDSZ_256: - mem_size+=256; - break; - case SDRAM_RXBAS_SDSZ_512: - mem_size+=512; - break; - case SDRAM_RXBAS_SDSZ_1024: - mem_size+=1024; - break; - case SDRAM_RXBAS_SDSZ_2048: - mem_size+=2048; - break; - case SDRAM_RXBAS_SDSZ_4096: - mem_size+=4096; - break; - default: - printf("WARNING: Unsupported bank size (SDSZ=0x%lx)!\n" - , sdsz); - mem_size=0; - break; - } - } - } - } - - return mem_size << 20; -} - -/*-----------------------------------------------------------------------------+ - * is_ecc_enabled - *-----------------------------------------------------------------------------*/ -static unsigned long is_ecc_enabled(void) -{ - unsigned long val; - - mfsdram(SDRAM_MCOPT1, val); - - return SDRAM_MCOPT1_MCHK_CHK_DECODE(val); -} - -/*-----------------------------------------------------------------------------+ - * board_add_ram_info - *-----------------------------------------------------------------------------*/ -void board_add_ram_info(int use_default) -{ - PPC4xx_SYS_INFO board_cfg; - u32 val; - - if (is_ecc_enabled()) - puts(" (ECC"); - else - puts(" (ECC not"); - - get_sys_info(&board_cfg); - -#if defined(CONFIG_405EX) - val = board_cfg.freqPLB; -#else - mfsdr(SDR0_DDR0, val); - val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1); -#endif - printf(" enabled, %d MHz", (val * 2) / 1000000); - - mfsdram(SDRAM_MMODE, val); - val = (val & SDRAM_MMODE_DCL_MASK) >> 4; - printf(", CL%d)", val); -} -#endif /* !CONFIG_NAND_SPL */ - -#if defined(CONFIG_SPD_EEPROM) - -/*-----------------------------------------------------------------------------+ - * Defines - *-----------------------------------------------------------------------------*/ -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define SDRAM_DDR1 1 -#define SDRAM_DDR2 2 -#define SDRAM_NONE 0 - -#define MAXDIMMS 2 -#define MAX_SPD_BYTES 256 /* Max number of bytes on the DIMM's SPD EEPROM */ - -#define ONE_BILLION 1000000000 - -#define CMD_NOP (7 << 19) -#define CMD_PRECHARGE (2 << 19) -#define CMD_REFRESH (1 << 19) -#define CMD_EMR (0 << 19) -#define CMD_READ (5 << 19) -#define CMD_WRITE (4 << 19) - -#define SELECT_MR (0 << 16) -#define SELECT_EMR (1 << 16) -#define SELECT_EMR2 (2 << 16) -#define SELECT_EMR3 (3 << 16) - -/* MR */ -#define DLL_RESET 0x00000100 - -#define WRITE_RECOV_2 (1 << 9) -#define WRITE_RECOV_3 (2 << 9) -#define WRITE_RECOV_4 (3 << 9) -#define WRITE_RECOV_5 (4 << 9) -#define WRITE_RECOV_6 (5 << 9) - -#define BURST_LEN_4 0x00000002 - -/* EMR */ -#define ODT_0_OHM 0x00000000 -#define ODT_50_OHM 0x00000044 -#define ODT_75_OHM 0x00000004 -#define ODT_150_OHM 0x00000040 - -#define ODS_FULL 0x00000000 -#define ODS_REDUCED 0x00000002 -#define OCD_CALIB_DEF 0x00000380 - -/* defines for ODT (On Die Termination) of the 440SP(e) DDR2 controller */ -#define ODT_EB0R (0x80000000 >> 8) -#define ODT_EB0W (0x80000000 >> 7) -#define CALC_ODT_R(n) (ODT_EB0R << (n << 1)) -#define CALC_ODT_W(n) (ODT_EB0W << (n << 1)) -#define CALC_ODT_RW(n) (CALC_ODT_R(n) | CALC_ODT_W(n)) - -/* Defines for the Read Cycle Delay test */ -#define NUMMEMTESTS 8 -#define NUMMEMWORDS 8 -#define NUMLOOPS 64 /* memory test loops */ - -/* - * Newer PPC's like 440SPe, 460EX/GT can be equipped with more than 2GB of SDRAM. - * To support such configurations, we "only" map the first 2GB via the TLB's. We - * need some free virtual address space for the remaining peripherals like, SoC - * devices, FLASH etc. - * - * Note that ECC is currently not supported on configurations with more than 2GB - * SDRAM. This is because we only map the first 2GB on such systems, and therefore - * the ECC parity byte of the remaining area can't be written. - */ - -/* - * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed - */ -void __spd_ddr_init_hang (void) -{ - hang (); -} -void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang"))); - -/* - * To provide an interface for board specific config values in this common - * DDR setup code, we implement he "weak" default functions here. They return - * the default value back to the caller. - * - * Please see include/configs/yucca.h for an example fora board specific - * implementation. - */ -u32 __ddr_wrdtr(u32 default_val) -{ - return default_val; -} -u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr"))); - -u32 __ddr_clktr(u32 default_val) -{ - return default_val; -} -u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr"))); - - -/* Private Structure Definitions */ - -/* enum only to ease code for cas latency setting */ -typedef enum ddr_cas_id { - DDR_CAS_2 = 20, - DDR_CAS_2_5 = 25, - DDR_CAS_3 = 30, - DDR_CAS_4 = 40, - DDR_CAS_5 = 50 -} ddr_cas_id_t; - -/*-----------------------------------------------------------------------------+ - * Prototypes - *-----------------------------------------------------------------------------*/ -static void get_spd_info(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void check_mem_type(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void check_frequency(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void check_rank_number(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void check_voltage_type(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_memory_queue(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_codt(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_mode(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks, - ddr_cas_id_t *selected_cas, - int *write_recovery); -static void program_tr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_rtr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_bxcf(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_copt1(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -static void program_initplr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks, - ddr_cas_id_t selected_cas, - int write_recovery); -#ifdef CONFIG_DDR_ECC -static void program_ecc(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks, - unsigned long tlb_word2_i_value); -#endif -#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) -static void program_DQS_calibration(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); -#ifdef HARD_CODED_DQS /* calibration test with hardvalues */ -static void test(void); -#else -static void DQS_calibration_process(void); -#endif -#endif - -static unsigned char spd_read(uchar chip, uint addr) -{ - unsigned char data[2]; - - if (i2c_probe(chip) == 0) - if (i2c_read(chip, addr, 1, data, 1) == 0) - return data[0]; - - return 0; -} - -/*-----------------------------------------------------------------------------+ - * initdram. Initializes the 440SP Memory Queue and DDR SDRAM controller. - * Note: This routine runs from flash with a stack set up in the chip's - * sram space. It is important that the routine does not require .sbss, .bss or - * .data sections. It also cannot call routines that require these sections. - *-----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------- - * Function: initdram - * Description: Configures SDRAM memory banks for DDR operation. - * Auto Memory Configuration option reads the DDR SDRAM EEPROMs - * via the IIC bus and then configures the DDR SDRAM memory - * banks appropriately. If Auto Memory Configuration is - * not used, it is assumed that no DIMM is plugged - *-----------------------------------------------------------------------------*/ -phys_size_t initdram(int board_type) -{ - unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; - unsigned char spd0[MAX_SPD_BYTES]; - unsigned char spd1[MAX_SPD_BYTES]; - unsigned char *dimm_spd[MAXDIMMS]; - unsigned long dimm_populated[MAXDIMMS] = {SDRAM_NONE, SDRAM_NONE}; - unsigned long num_dimm_banks; /* on board dimm banks */ - unsigned long val; - ddr_cas_id_t selected_cas = DDR_CAS_5; /* preset to silence compiler */ - int write_recovery; - phys_size_t dram_size = 0; - - num_dimm_banks = sizeof(iic0_dimm_addr); - - /*------------------------------------------------------------------ - * Set up an array of SPD matrixes. - *-----------------------------------------------------------------*/ - dimm_spd[0] = spd0; - dimm_spd[1] = spd1; - - /*------------------------------------------------------------------ - * Reset the DDR-SDRAM controller. - *-----------------------------------------------------------------*/ - mtsdr(SDR0_SRST, SDR0_SRST0_DMC); - mtsdr(SDR0_SRST, 0x00000000); - - /* - * Make sure I2C controller is initialized - * before continuing. - */ - - /* switch to correct I2C bus */ - I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM); - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - - /*------------------------------------------------------------------ - * Clear out the serial presence detect buffers. - * Perform IIC reads from the dimm. Fill in the spds. - * Check to see if the dimm slots are populated - *-----------------------------------------------------------------*/ - get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Check the memory type for the dimms plugged. - *-----------------------------------------------------------------*/ - check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Check the frequency supported for the dimms plugged. - *-----------------------------------------------------------------*/ - check_frequency(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Check the total rank number. - *-----------------------------------------------------------------*/ - check_rank_number(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Check the voltage type for the dimms plugged. - *-----------------------------------------------------------------*/ - check_voltage_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Program SDRAM controller options 2 register - * Except Enabling of the memory controller. - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_MCOPT2, val); - mtsdram(SDRAM_MCOPT2, - (val & - ~(SDRAM_MCOPT2_SREN_MASK | SDRAM_MCOPT2_PMEN_MASK | - SDRAM_MCOPT2_IPTR_MASK | SDRAM_MCOPT2_XSRP_MASK | - SDRAM_MCOPT2_ISIE_MASK)) - | (SDRAM_MCOPT2_SREN_ENTER | SDRAM_MCOPT2_PMEN_DISABLE | - SDRAM_MCOPT2_IPTR_IDLE | SDRAM_MCOPT2_XSRP_ALLOW | - SDRAM_MCOPT2_ISIE_ENABLE)); - - /*------------------------------------------------------------------ - * Program SDRAM controller options 1 register - * Note: Does not enable the memory controller. - *-----------------------------------------------------------------*/ - program_copt1(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Set the SDRAM Controller On Die Termination Register - *-----------------------------------------------------------------*/ - program_codt(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Program SDRAM refresh register. - *-----------------------------------------------------------------*/ - program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Program SDRAM mode register. - *-----------------------------------------------------------------*/ - program_mode(dimm_populated, iic0_dimm_addr, num_dimm_banks, - &selected_cas, &write_recovery); - - /*------------------------------------------------------------------ - * Set the SDRAM Write Data/DM/DQS Clock Timing Reg - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_WRDTR, val); - mtsdram(SDRAM_WRDTR, (val & ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) | - ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | SDRAM_WRDTR_WTR_90_DEG_ADV)); - - /*------------------------------------------------------------------ - * Set the SDRAM Clock Timing Register - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_CLKTR, val); - mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) | - ddr_clktr(SDRAM_CLKTR_CLKP_0_DEG)); - - /*------------------------------------------------------------------ - * Program the BxCF registers. - *-----------------------------------------------------------------*/ - program_bxcf(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Program SDRAM timing registers. - *-----------------------------------------------------------------*/ - program_tr(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Set the Extended Mode register - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_MEMODE, val); - mtsdram(SDRAM_MEMODE, - (val & ~(SDRAM_MEMODE_DIC_MASK | SDRAM_MEMODE_DLL_MASK | - SDRAM_MEMODE_RTT_MASK | SDRAM_MEMODE_DQS_MASK)) | - (SDRAM_MEMODE_DIC_NORMAL | SDRAM_MEMODE_DLL_ENABLE - | SDRAM_MEMODE_RTT_150OHM | SDRAM_MEMODE_DQS_ENABLE)); - - /*------------------------------------------------------------------ - * Program Initialization preload registers. - *-----------------------------------------------------------------*/ - program_initplr(dimm_populated, iic0_dimm_addr, num_dimm_banks, - selected_cas, write_recovery); - - /*------------------------------------------------------------------ - * Delay to ensure 200usec have elapsed since reset. - *-----------------------------------------------------------------*/ - udelay(400); - - /*------------------------------------------------------------------ - * Set the memory queue core base addr. - *-----------------------------------------------------------------*/ - program_memory_queue(dimm_populated, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Program SDRAM controller options 2 register - * Enable the memory controller. - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_MCOPT2, val); - mtsdram(SDRAM_MCOPT2, - (val & ~(SDRAM_MCOPT2_SREN_MASK | SDRAM_MCOPT2_DCEN_MASK | - SDRAM_MCOPT2_IPTR_MASK | SDRAM_MCOPT2_ISIE_MASK)) | - SDRAM_MCOPT2_IPTR_EXECUTE); - - /*------------------------------------------------------------------ - * Wait for IPTR_EXECUTE init sequence to complete. - *-----------------------------------------------------------------*/ - do { - mfsdram(SDRAM_MCSTAT, val); - } while ((val & SDRAM_MCSTAT_MIC_MASK) == SDRAM_MCSTAT_MIC_NOTCOMP); - - /* enable the controller only after init sequence completes */ - mfsdram(SDRAM_MCOPT2, val); - mtsdram(SDRAM_MCOPT2, (val | SDRAM_MCOPT2_DCEN_ENABLE)); - - /* Make sure delay-line calibration is done before proceeding */ - do { - mfsdram(SDRAM_DLCR, val); - } while (!(val & SDRAM_DLCR_DLCS_COMPLETE)); - - /* get installed memory size */ - dram_size = sdram_memsize(); - - /* - * Limit size to 2GB - */ - if (dram_size > CONFIG_MAX_MEM_MAPPED) - dram_size = CONFIG_MAX_MEM_MAPPED; - - /* and program tlb entries for this size (dynamic) */ - - /* - * Program TLB entries with caches enabled, for best performace - * while auto-calibrating and ECC generation - */ - program_tlb(0, 0, dram_size, 0); - - /*------------------------------------------------------------------ - * DQS calibration. - *-----------------------------------------------------------------*/ -#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) - DQS_autocalibration(); -#else - program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks); -#endif - /* - * Now complete RDSS configuration as mentioned on page 7 of the AMCC - * PowerPC440SP/SPe DDR2 application note: - * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning" - */ - update_rdcc(); - -#ifdef CONFIG_DDR_ECC - /*------------------------------------------------------------------ - * If ecc is enabled, initialize the parity bits. - *-----------------------------------------------------------------*/ - program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks, 0); -#endif - - /* - * Now after initialization (auto-calibration and ECC generation) - * remove the TLB entries with caches enabled and program again with - * desired cache functionality - */ - remove_tlb(0, dram_size); - program_tlb(0, 0, dram_size, MY_TLB_WORD2_I_ENABLE); - - ppc4xx_ibm_ddr2_register_dump(); - - /* - * Clear potential errors resulting from auto-calibration. - * If not done, then we could get an interrupt later on when - * exceptions are enabled. - */ - set_mcsr(get_mcsr()); - - return sdram_memsize(); -} - -static void get_spd_info(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long dimm_found; - unsigned char num_of_bytes; - unsigned char total_size; - - dimm_found = FALSE; - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - num_of_bytes = 0; - total_size = 0; - - num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0); - debug("\nspd_read(0x%x) returned %d\n", - iic0_dimm_addr[dimm_num], num_of_bytes); - total_size = spd_read(iic0_dimm_addr[dimm_num], 1); - debug("spd_read(0x%x) returned %d\n", - iic0_dimm_addr[dimm_num], total_size); - - if ((num_of_bytes != 0) && (total_size != 0)) { - dimm_populated[dimm_num] = TRUE; - dimm_found = TRUE; - debug("DIMM slot %lu: populated\n", dimm_num); - } else { - dimm_populated[dimm_num] = FALSE; - debug("DIMM slot %lu: Not populated\n", dimm_num); - } - } - - if (dimm_found == FALSE) { - printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n"); - spd_ddr_init_hang (); - } -} - - -/*------------------------------------------------------------------ - * For the memory DIMMs installed, this routine verifies that they - * really are DDR specific DIMMs. - *-----------------------------------------------------------------*/ -static void check_mem_type(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long dimm_type; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] == TRUE) { - dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2); - switch (dimm_type) { - case 1: - printf("ERROR: Standard Fast Page Mode DRAM DIMM detected in " - "slot %d.\n", (unsigned int)dimm_num); - printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - case 2: - printf("ERROR: EDO DIMM detected in slot %d.\n", - (unsigned int)dimm_num); - printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - case 3: - printf("ERROR: Pipelined Nibble DIMM detected in slot %d.\n", - (unsigned int)dimm_num); - printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - case 4: - printf("ERROR: SDRAM DIMM detected in slot %d.\n", - (unsigned int)dimm_num); - printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - case 5: - printf("ERROR: Multiplexed ROM DIMM detected in slot %d.\n", - (unsigned int)dimm_num); - printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - case 6: - printf("ERROR: SGRAM DIMM detected in slot %d.\n", - (unsigned int)dimm_num); - printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - case 7: - debug("DIMM slot %lu: DDR1 SDRAM detected\n", dimm_num); - dimm_populated[dimm_num] = SDRAM_DDR1; - break; - case 8: - debug("DIMM slot %lu: DDR2 SDRAM detected\n", dimm_num); - dimm_populated[dimm_num] = SDRAM_DDR2; - break; - default: - printf("ERROR: Unknown DIMM detected in slot %d.\n", - (unsigned int)dimm_num); - printf("Only DDR1 and DDR2 SDRAM DIMMs are supported.\n"); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - } - } - } - for (dimm_num = 1; dimm_num < num_dimm_banks; dimm_num++) { - if ((dimm_populated[dimm_num-1] != SDRAM_NONE) - && (dimm_populated[dimm_num] != SDRAM_NONE) - && (dimm_populated[dimm_num-1] != dimm_populated[dimm_num])) { - printf("ERROR: DIMM's DDR1 and DDR2 type can not be mixed.\n"); - spd_ddr_init_hang (); - } - } -} - -/*------------------------------------------------------------------ - * For the memory DIMMs installed, this routine verifies that - * frequency previously calculated is supported. - *-----------------------------------------------------------------*/ -static void check_frequency(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long tcyc_reg; - unsigned long cycle_time; - unsigned long calc_cycle_time; - unsigned long sdram_freq; - unsigned long sdr_ddrpll; - PPC4xx_SYS_INFO board_cfg; - - /*------------------------------------------------------------------ - * Get the board configuration info. - *-----------------------------------------------------------------*/ - get_sys_info(&board_cfg); - - mfsdr(SDR0_DDR0, sdr_ddrpll); - sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); - - /* - * calc_cycle_time is calculated from DDR frequency set by board/chip - * and is expressed in multiple of 10 picoseconds - * to match the way DIMM cycle time is calculated below. - */ - calc_cycle_time = MULDIV64(ONE_BILLION, 100, sdram_freq); - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] != SDRAM_NONE) { - tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9); - /* - * Byte 9, Cycle time for CAS Latency=X, is split into two nibbles: - * the higher order nibble (bits 4-7) designates the cycle time - * to a granularity of 1ns; - * the value presented by the lower order nibble (bits 0-3) - * has a granularity of .1ns and is added to the value designated - * by the higher nibble. In addition, four lines of the lower order - * nibble are assigned to support +.25,+.33, +.66 and +.75. - */ - /* Convert from hex to decimal */ - if ((tcyc_reg & 0x0F) == 0x0D) - cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 75; - else if ((tcyc_reg & 0x0F) == 0x0C) - cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 66; - else if ((tcyc_reg & 0x0F) == 0x0B) - cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 33; - else if ((tcyc_reg & 0x0F) == 0x0A) - cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 25; - else - cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + - ((tcyc_reg & 0x0F)*10); - debug("cycle_time=%lu [10 picoseconds]\n", cycle_time); - - if (cycle_time > (calc_cycle_time + 10)) { - /* - * the provided sdram cycle_time is too small - * for the available DIMM cycle_time. - * The additionnal 100ps is here to accept a small incertainty. - */ - printf("ERROR: DRAM DIMM detected with cycle_time %d ps in " - "slot %d \n while calculated cycle time is %d ps.\n", - (unsigned int)(cycle_time*10), - (unsigned int)dimm_num, - (unsigned int)(calc_cycle_time*10)); - printf("Replace the DIMM, or change DDR frequency via " - "strapping bits.\n\n"); - spd_ddr_init_hang (); - } - } - } -} - -/*------------------------------------------------------------------ - * For the memory DIMMs installed, this routine verifies two - * ranks/banks maximum are availables. - *-----------------------------------------------------------------*/ -static void check_rank_number(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long dimm_rank; - unsigned long total_rank = 0; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] != SDRAM_NONE) { - dimm_rank = spd_read(iic0_dimm_addr[dimm_num], 5); - if (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) - dimm_rank = (dimm_rank & 0x0F) +1; - else - dimm_rank = dimm_rank & 0x0F; - - - if (dimm_rank > MAXRANKS) { - printf("ERROR: DRAM DIMM detected with %lu ranks in " - "slot %lu is not supported.\n", dimm_rank, dimm_num); - printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - } else - total_rank += dimm_rank; - } - if (total_rank > MAXRANKS) { - printf("ERROR: DRAM DIMM detected with a total of %d ranks " - "for all slots.\n", (unsigned int)total_rank); - printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS); - printf("Remove one of the DIMM modules.\n\n"); - spd_ddr_init_hang (); - } - } -} - -/*------------------------------------------------------------------ - * only support 2.5V modules. - * This routine verifies this. - *-----------------------------------------------------------------*/ -static void check_voltage_type(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long voltage_type; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] != SDRAM_NONE) { - voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8); - switch (voltage_type) { - case 0x00: - printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); - printf("This DIMM is 5.0 Volt/TTL.\n"); - printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", - (unsigned int)dimm_num); - spd_ddr_init_hang (); - break; - case 0x01: - printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); - printf("This DIMM is LVTTL.\n"); - printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", - (unsigned int)dimm_num); - spd_ddr_init_hang (); - break; - case 0x02: - printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); - printf("This DIMM is 1.5 Volt.\n"); - printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", - (unsigned int)dimm_num); - spd_ddr_init_hang (); - break; - case 0x03: - printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); - printf("This DIMM is 3.3 Volt/TTL.\n"); - printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", - (unsigned int)dimm_num); - spd_ddr_init_hang (); - break; - case 0x04: - /* 2.5 Voltage only for DDR1 */ - break; - case 0x05: - /* 1.8 Voltage only for DDR2 */ - break; - default: - printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); - printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", - (unsigned int)dimm_num); - spd_ddr_init_hang (); - break; - } - } - } -} - -/*-----------------------------------------------------------------------------+ - * program_copt1. - *-----------------------------------------------------------------------------*/ -static void program_copt1(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long mcopt1; - unsigned long ecc_enabled; - unsigned long ecc = 0; - unsigned long data_width = 0; - unsigned long dimm_32bit; - unsigned long dimm_64bit; - unsigned long registered = 0; - unsigned long attribute = 0; - unsigned long buf0, buf1; /* TODO: code to be changed for IOP1.6 to support 4 DIMMs */ - unsigned long bankcount; - unsigned long ddrtype; - unsigned long val; - -#ifdef CONFIG_DDR_ECC - ecc_enabled = TRUE; -#else - ecc_enabled = FALSE; -#endif - dimm_32bit = FALSE; - dimm_64bit = FALSE; - buf0 = FALSE; - buf1 = FALSE; - - /*------------------------------------------------------------------ - * Set memory controller options reg 1, SDRAM_MCOPT1. - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_MCOPT1, val); - mcopt1 = val & ~(SDRAM_MCOPT1_MCHK_MASK | SDRAM_MCOPT1_RDEN_MASK | - SDRAM_MCOPT1_PMU_MASK | SDRAM_MCOPT1_DMWD_MASK | - SDRAM_MCOPT1_UIOS_MASK | SDRAM_MCOPT1_BCNT_MASK | - SDRAM_MCOPT1_DDR_TYPE_MASK | SDRAM_MCOPT1_RWOO_MASK | - SDRAM_MCOPT1_WOOO_MASK | SDRAM_MCOPT1_DCOO_MASK | - SDRAM_MCOPT1_DREF_MASK); - - mcopt1 |= SDRAM_MCOPT1_QDEP; - mcopt1 |= SDRAM_MCOPT1_PMU_OPEN; - mcopt1 |= SDRAM_MCOPT1_RWOO_DISABLED; - mcopt1 |= SDRAM_MCOPT1_WOOO_DISABLED; - mcopt1 |= SDRAM_MCOPT1_DCOO_DISABLED; - mcopt1 |= SDRAM_MCOPT1_DREF_NORMAL; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] != SDRAM_NONE) { - /* test ecc support */ - ecc = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 11); - if (ecc != 0x02) /* ecc not supported */ - ecc_enabled = FALSE; - - /* test bank count */ - bankcount = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 17); - if (bankcount == 0x04) /* bank count = 4 */ - mcopt1 |= SDRAM_MCOPT1_4_BANKS; - else /* bank count = 8 */ - mcopt1 |= SDRAM_MCOPT1_8_BANKS; - - /* test DDR type */ - ddrtype = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2); - /* test for buffered/unbuffered, registered, differential clocks */ - registered = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 20); - attribute = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 21); - - /* TODO: code to be changed for IOP1.6 to support 4 DIMMs */ - if (dimm_num == 0) { - if (dimm_populated[dimm_num] == SDRAM_DDR1) /* DDR1 type */ - mcopt1 |= SDRAM_MCOPT1_DDR1_TYPE; - if (dimm_populated[dimm_num] == SDRAM_DDR2) /* DDR2 type */ - mcopt1 |= SDRAM_MCOPT1_DDR2_TYPE; - if (registered == 1) { /* DDR2 always buffered */ - /* TODO: what about above comments ? */ - mcopt1 |= SDRAM_MCOPT1_RDEN; - buf0 = TRUE; - } else { - /* TODO: the mask 0x02 doesn't match Samsung def for byte 21. */ - if ((attribute & 0x02) == 0x00) { - /* buffered not supported */ - buf0 = FALSE; - } else { - mcopt1 |= SDRAM_MCOPT1_RDEN; - buf0 = TRUE; - } - } - } - else if (dimm_num == 1) { - if (dimm_populated[dimm_num] == SDRAM_DDR1) /* DDR1 type */ - mcopt1 |= SDRAM_MCOPT1_DDR1_TYPE; - if (dimm_populated[dimm_num] == SDRAM_DDR2) /* DDR2 type */ - mcopt1 |= SDRAM_MCOPT1_DDR2_TYPE; - if (registered == 1) { - /* DDR2 always buffered */ - mcopt1 |= SDRAM_MCOPT1_RDEN; - buf1 = TRUE; - } else { - if ((attribute & 0x02) == 0x00) { - /* buffered not supported */ - buf1 = FALSE; - } else { - mcopt1 |= SDRAM_MCOPT1_RDEN; - buf1 = TRUE; - } - } - } - - /* Note that for DDR2 the byte 7 is reserved, but OK to keep code as is. */ - data_width = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 6) + - (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 7)) << 8); - - switch (data_width) { - case 72: - case 64: - dimm_64bit = TRUE; - break; - case 40: - case 32: - dimm_32bit = TRUE; - break; - default: - printf("WARNING: Detected a DIMM with a data width of %lu bits.\n", - data_width); - printf("Only DIMMs with 32 or 64 bit DDR-SDRAM widths are supported.\n"); - break; - } - } - } - - /* verify matching properties */ - if ((dimm_populated[0] != SDRAM_NONE) && (dimm_populated[1] != SDRAM_NONE)) { - if (buf0 != buf1) { - printf("ERROR: DIMM's buffered/unbuffered, registered, clocking don't match.\n"); - spd_ddr_init_hang (); - } - } - - if ((dimm_64bit == TRUE) && (dimm_32bit == TRUE)) { - printf("ERROR: Cannot mix 32 bit and 64 bit DDR-SDRAM DIMMs together.\n"); - spd_ddr_init_hang (); - } - else if ((dimm_64bit == TRUE) && (dimm_32bit == FALSE)) { - mcopt1 |= SDRAM_MCOPT1_DMWD_64; - } else if ((dimm_64bit == FALSE) && (dimm_32bit == TRUE)) { - mcopt1 |= SDRAM_MCOPT1_DMWD_32; - } else { - printf("ERROR: Please install only 32 or 64 bit DDR-SDRAM DIMMs.\n\n"); - spd_ddr_init_hang (); - } - - if (ecc_enabled == TRUE) - mcopt1 |= SDRAM_MCOPT1_MCHK_GEN; - else - mcopt1 |= SDRAM_MCOPT1_MCHK_NON; - - mtsdram(SDRAM_MCOPT1, mcopt1); -} - -/*-----------------------------------------------------------------------------+ - * program_codt. - *-----------------------------------------------------------------------------*/ -static void program_codt(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long codt; - unsigned long modt0 = 0; - unsigned long modt1 = 0; - unsigned long modt2 = 0; - unsigned long modt3 = 0; - unsigned char dimm_num; - unsigned char dimm_rank; - unsigned char total_rank = 0; - unsigned char total_dimm = 0; - unsigned char dimm_type = 0; - unsigned char firstSlot = 0; - - /*------------------------------------------------------------------ - * Set the SDRAM Controller On Die Termination Register - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_CODT, codt); - codt &= ~(SDRAM_CODT_DQS_SINGLE_END | SDRAM_CODT_CKSE_SINGLE_END); - codt |= SDRAM_CODT_IO_NMODE; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] != SDRAM_NONE) { - dimm_rank = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 5); - if (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) { - dimm_rank = (dimm_rank & 0x0F) + 1; - dimm_type = SDRAM_DDR2; - } else { - dimm_rank = dimm_rank & 0x0F; - dimm_type = SDRAM_DDR1; - } - - total_rank += dimm_rank; - total_dimm++; - if ((dimm_num == 0) && (total_dimm == 1)) - firstSlot = TRUE; - else - firstSlot = FALSE; - } - } - if (dimm_type == SDRAM_DDR2) { - codt |= SDRAM_CODT_DQS_1_8_V_DDR2; - if ((total_dimm == 1) && (firstSlot == TRUE)) { - if (total_rank == 1) { /* PUUU */ - codt |= CALC_ODT_R(0); - modt0 = CALC_ODT_W(0); - modt1 = 0x00000000; - modt2 = 0x00000000; - modt3 = 0x00000000; - } - if (total_rank == 2) { /* PPUU */ - codt |= CALC_ODT_R(0) | CALC_ODT_R(1); - modt0 = CALC_ODT_W(0) | CALC_ODT_W(1); - modt1 = 0x00000000; - modt2 = 0x00000000; - modt3 = 0x00000000; - } - } else if ((total_dimm == 1) && (firstSlot != TRUE)) { - if (total_rank == 1) { /* UUPU */ - codt |= CALC_ODT_R(2); - modt0 = 0x00000000; - modt1 = 0x00000000; - modt2 = CALC_ODT_W(2); - modt3 = 0x00000000; - } - if (total_rank == 2) { /* UUPP */ - codt |= CALC_ODT_R(2) | CALC_ODT_R(3); - modt0 = 0x00000000; - modt1 = 0x00000000; - modt2 = CALC_ODT_W(2) | CALC_ODT_W(3); - modt3 = 0x00000000; - } - } - if (total_dimm == 2) { - if (total_rank == 2) { /* PUPU */ - codt |= CALC_ODT_R(0) | CALC_ODT_R(2); - modt0 = CALC_ODT_RW(2); - modt1 = 0x00000000; - modt2 = CALC_ODT_RW(0); - modt3 = 0x00000000; - } - if (total_rank == 4) { /* PPPP */ - codt |= CALC_ODT_R(0) | CALC_ODT_R(1) | - CALC_ODT_R(2) | CALC_ODT_R(3); - modt0 = CALC_ODT_RW(2) | CALC_ODT_RW(3); - modt1 = 0x00000000; - modt2 = CALC_ODT_RW(0) | CALC_ODT_RW(1); - modt3 = 0x00000000; - } - } - } else { - codt |= SDRAM_CODT_DQS_2_5_V_DDR1; - modt0 = 0x00000000; - modt1 = 0x00000000; - modt2 = 0x00000000; - modt3 = 0x00000000; - - if (total_dimm == 1) { - if (total_rank == 1) - codt |= 0x00800000; - if (total_rank == 2) - codt |= 0x02800000; - } - if (total_dimm == 2) { - if (total_rank == 2) - codt |= 0x08800000; - if (total_rank == 4) - codt |= 0x2a800000; - } - } - - debug("nb of dimm %d\n", total_dimm); - debug("nb of rank %d\n", total_rank); - if (total_dimm == 1) - debug("dimm in slot %d\n", firstSlot); - - mtsdram(SDRAM_CODT, codt); - mtsdram(SDRAM_MODT0, modt0); - mtsdram(SDRAM_MODT1, modt1); - mtsdram(SDRAM_MODT2, modt2); - mtsdram(SDRAM_MODT3, modt3); -} - -/*-----------------------------------------------------------------------------+ - * program_initplr. - *-----------------------------------------------------------------------------*/ -static void program_initplr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks, - ddr_cas_id_t selected_cas, - int write_recovery) -{ - u32 cas = 0; - u32 odt = 0; - u32 ods = 0; - u32 mr; - u32 wr; - u32 emr; - u32 emr2; - u32 emr3; - int dimm_num; - int total_dimm = 0; - - /****************************************************** - ** Assumption: if more than one DIMM, all DIMMs are the same - ** as already checked in check_memory_type - ******************************************************/ - - if ((dimm_populated[0] == SDRAM_DDR1) || (dimm_populated[1] == SDRAM_DDR1)) { - mtsdram(SDRAM_INITPLR0, 0x81B80000); - mtsdram(SDRAM_INITPLR1, 0x81900400); - mtsdram(SDRAM_INITPLR2, 0x81810000); - mtsdram(SDRAM_INITPLR3, 0xff800162); - mtsdram(SDRAM_INITPLR4, 0x81900400); - mtsdram(SDRAM_INITPLR5, 0x86080000); - mtsdram(SDRAM_INITPLR6, 0x86080000); - mtsdram(SDRAM_INITPLR7, 0x81000062); - } else if ((dimm_populated[0] == SDRAM_DDR2) || (dimm_populated[1] == SDRAM_DDR2)) { - switch (selected_cas) { - case DDR_CAS_3: - cas = 3 << 4; - break; - case DDR_CAS_4: - cas = 4 << 4; - break; - case DDR_CAS_5: - cas = 5 << 4; - break; - default: - printf("ERROR: ucode error on selected_cas value %d", selected_cas); - spd_ddr_init_hang (); - break; - } - -#if 0 - /* - * ToDo - Still a problem with the write recovery: - * On the Corsair CM2X512-5400C4 module, setting write recovery - * in the INITPLR reg to the value calculated in program_mode() - * results in not correctly working DDR2 memory (crash after - * relocation). - * - * So for now, set the write recovery to 3. This seems to work - * on the Corair module too. - * - * 2007-03-01, sr - */ - switch (write_recovery) { - case 3: - wr = WRITE_RECOV_3; - break; - case 4: - wr = WRITE_RECOV_4; - break; - case 5: - wr = WRITE_RECOV_5; - break; - case 6: - wr = WRITE_RECOV_6; - break; - default: - printf("ERROR: write recovery not support (%d)", write_recovery); - spd_ddr_init_hang (); - break; - } -#else - wr = WRITE_RECOV_3; /* test-only, see description above */ -#endif - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) - if (dimm_populated[dimm_num] != SDRAM_NONE) - total_dimm++; - if (total_dimm == 1) { - odt = ODT_150_OHM; - ods = ODS_FULL; - } else if (total_dimm == 2) { - odt = ODT_75_OHM; - ods = ODS_REDUCED; - } else { - printf("ERROR: Unsupported number of DIMM's (%d)", total_dimm); - spd_ddr_init_hang (); - } - - mr = CMD_EMR | SELECT_MR | BURST_LEN_4 | wr | cas; - emr = CMD_EMR | SELECT_EMR | odt | ods; - emr2 = CMD_EMR | SELECT_EMR2; - emr3 = CMD_EMR | SELECT_EMR3; - /* NOP - Wait 106 MemClk cycles */ - mtsdram(SDRAM_INITPLR0, SDRAM_INITPLR_ENABLE | CMD_NOP | - SDRAM_INITPLR_IMWT_ENCODE(106)); - udelay(1000); - /* precharge 4 MemClk cycles */ - mtsdram(SDRAM_INITPLR1, SDRAM_INITPLR_ENABLE | CMD_PRECHARGE | - SDRAM_INITPLR_IMWT_ENCODE(4)); - /* EMR2 - Wait tMRD (2 MemClk cycles) */ - mtsdram(SDRAM_INITPLR2, SDRAM_INITPLR_ENABLE | emr2 | - SDRAM_INITPLR_IMWT_ENCODE(2)); - /* EMR3 - Wait tMRD (2 MemClk cycles) */ - mtsdram(SDRAM_INITPLR3, SDRAM_INITPLR_ENABLE | emr3 | - SDRAM_INITPLR_IMWT_ENCODE(2)); - /* EMR DLL ENABLE - Wait tMRD (2 MemClk cycles) */ - mtsdram(SDRAM_INITPLR4, SDRAM_INITPLR_ENABLE | emr | - SDRAM_INITPLR_IMWT_ENCODE(2)); - /* MR w/ DLL reset - 200 cycle wait for DLL reset */ - mtsdram(SDRAM_INITPLR5, SDRAM_INITPLR_ENABLE | mr | DLL_RESET | - SDRAM_INITPLR_IMWT_ENCODE(200)); - udelay(1000); - /* precharge 4 MemClk cycles */ - mtsdram(SDRAM_INITPLR6, SDRAM_INITPLR_ENABLE | CMD_PRECHARGE | - SDRAM_INITPLR_IMWT_ENCODE(4)); - /* Refresh 25 MemClk cycles */ - mtsdram(SDRAM_INITPLR7, SDRAM_INITPLR_ENABLE | CMD_REFRESH | - SDRAM_INITPLR_IMWT_ENCODE(25)); - /* Refresh 25 MemClk cycles */ - mtsdram(SDRAM_INITPLR8, SDRAM_INITPLR_ENABLE | CMD_REFRESH | - SDRAM_INITPLR_IMWT_ENCODE(25)); - /* Refresh 25 MemClk cycles */ - mtsdram(SDRAM_INITPLR9, SDRAM_INITPLR_ENABLE | CMD_REFRESH | - SDRAM_INITPLR_IMWT_ENCODE(25)); - /* Refresh 25 MemClk cycles */ - mtsdram(SDRAM_INITPLR10, SDRAM_INITPLR_ENABLE | CMD_REFRESH | - SDRAM_INITPLR_IMWT_ENCODE(25)); - /* MR w/o DLL reset - Wait tMRD (2 MemClk cycles) */ - mtsdram(SDRAM_INITPLR11, SDRAM_INITPLR_ENABLE | mr | - SDRAM_INITPLR_IMWT_ENCODE(2)); - /* EMR OCD Default - Wait tMRD (2 MemClk cycles) */ - mtsdram(SDRAM_INITPLR12, SDRAM_INITPLR_ENABLE | OCD_CALIB_DEF | - SDRAM_INITPLR_IMWT_ENCODE(2) | emr); - /* EMR OCD Exit */ - mtsdram(SDRAM_INITPLR13, SDRAM_INITPLR_ENABLE | emr | - SDRAM_INITPLR_IMWT_ENCODE(2)); - } else { - printf("ERROR: ucode error as unknown DDR type in program_initplr"); - spd_ddr_init_hang (); - } -} - -/*------------------------------------------------------------------ - * This routine programs the SDRAM_MMODE register. - * the selected_cas is an output parameter, that will be passed - * by caller to call the above program_initplr( ) - *-----------------------------------------------------------------*/ -static void program_mode(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks, - ddr_cas_id_t *selected_cas, - int *write_recovery) -{ - unsigned long dimm_num; - unsigned long sdram_ddr1; - unsigned long t_wr_ns; - unsigned long t_wr_clk; - unsigned long cas_bit; - unsigned long cas_index; - unsigned long sdram_freq; - unsigned long ddr_check; - unsigned long mmode; - unsigned long tcyc_reg; - unsigned long cycle_2_0_clk; - unsigned long cycle_2_5_clk; - unsigned long cycle_3_0_clk; - unsigned long cycle_4_0_clk; - unsigned long cycle_5_0_clk; - unsigned long max_2_0_tcyc_ns_x_100; - unsigned long max_2_5_tcyc_ns_x_100; - unsigned long max_3_0_tcyc_ns_x_100; - unsigned long max_4_0_tcyc_ns_x_100; - unsigned long max_5_0_tcyc_ns_x_100; - unsigned long cycle_time_ns_x_100[3]; - PPC4xx_SYS_INFO board_cfg; - unsigned char cas_2_0_available; - unsigned char cas_2_5_available; - unsigned char cas_3_0_available; - unsigned char cas_4_0_available; - unsigned char cas_5_0_available; - unsigned long sdr_ddrpll; - - /*------------------------------------------------------------------ - * Get the board configuration info. - *-----------------------------------------------------------------*/ - get_sys_info(&board_cfg); - - mfsdr(SDR0_DDR0, sdr_ddrpll); - sdram_freq = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(sdr_ddrpll), 1); - debug("sdram_freq=%lu\n", sdram_freq); - - /*------------------------------------------------------------------ - * Handle the timing. We need to find the worst case timing of all - * the dimm modules installed. - *-----------------------------------------------------------------*/ - t_wr_ns = 0; - cas_2_0_available = TRUE; - cas_2_5_available = TRUE; - cas_3_0_available = TRUE; - cas_4_0_available = TRUE; - cas_5_0_available = TRUE; - max_2_0_tcyc_ns_x_100 = 10; - max_2_5_tcyc_ns_x_100 = 10; - max_3_0_tcyc_ns_x_100 = 10; - max_4_0_tcyc_ns_x_100 = 10; - max_5_0_tcyc_ns_x_100 = 10; - sdram_ddr1 = TRUE; - - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_populated[dimm_num] != SDRAM_NONE) { - if (dimm_populated[dimm_num] == SDRAM_DDR1) - sdram_ddr1 = TRUE; - else - sdram_ddr1 = FALSE; - - /* t_wr_ns = max(t_wr_ns, (unsigned long)dimm_spd[dimm_num][36] >> 2); */ /* not used in this loop. */ - cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18); - debug("cas_bit[SPD byte 18]=%02lx\n", cas_bit); - - /* For a particular DIMM, grab the three CAS values it supports */ - for (cas_index = 0; cas_index < 3; cas_index++) { - switch (cas_index) { - case 0: - tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9); - break; - case 1: - tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23); - break; - default: - tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25); - break; - } - - if ((tcyc_reg & 0x0F) >= 10) { - if ((tcyc_reg & 0x0F) == 0x0D) { - /* Convert from hex to decimal */ - cycle_time_ns_x_100[cas_index] = - (((tcyc_reg & 0xF0) >> 4) * 100) + 75; - } else { - printf("ERROR: SPD reported Tcyc is incorrect for DIMM " - "in slot %d\n", (unsigned int)dimm_num); - spd_ddr_init_hang (); - } - } else { - /* Convert from hex to decimal */ - cycle_time_ns_x_100[cas_index] = - (((tcyc_reg & 0xF0) >> 4) * 100) + - ((tcyc_reg & 0x0F)*10); - } - debug("cas_index=%lu: cycle_time_ns_x_100=%lu\n", cas_index, - cycle_time_ns_x_100[cas_index]); - } - - /* The rest of this routine determines if CAS 2.0, 2.5, 3.0, 4.0 and 5.0 are */ - /* supported for a particular DIMM. */ - cas_index = 0; - - if (sdram_ddr1) { - /* - * DDR devices use the following bitmask for CAS latency: - * Bit 7 6 5 4 3 2 1 0 - * TBD 4.0 3.5 3.0 2.5 2.0 1.5 1.0 - */ - if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) && - (cycle_time_ns_x_100[cas_index] != 0)) { - max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, - cycle_time_ns_x_100[cas_index]); - cas_index++; - } else { - if (cas_index != 0) - cas_index++; - cas_4_0_available = FALSE; - } - - if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && - (cycle_time_ns_x_100[cas_index] != 0)) { - max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, - cycle_time_ns_x_100[cas_index]); - cas_index++; - } else { - if (cas_index != 0) - cas_index++; - cas_3_0_available = FALSE; - } - - if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && - (cycle_time_ns_x_100[cas_index] != 0)) { - max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100, - cycle_time_ns_x_100[cas_index]); - cas_index++; - } else { - if (cas_index != 0) - cas_index++; - cas_2_5_available = FALSE; - } - - if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) && - (cycle_time_ns_x_100[cas_index] != 0)) { - max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100, - cycle_time_ns_x_100[cas_index]); - cas_index++; - } else { - if (cas_index != 0) - cas_index++; - cas_2_0_available = FALSE; - } - } else { - /* - * DDR2 devices use the following bitmask for CAS latency: - * Bit 7 6 5 4 3 2 1 0 - * TBD 6.0 5.0 4.0 3.0 2.0 TBD TBD - */ - if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) && - (cycle_time_ns_x_100[cas_index] != 0)) { - max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100, - cycle_time_ns_x_100[cas_index]); - cas_index++; - } else { - if (cas_index != 0) - cas_index++; - cas_5_0_available = FALSE; - } - - if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && - (cycle_time_ns_x_100[cas_index] != 0)) { - max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, - cycle_time_ns_x_100[cas_index]); - cas_index++; - } else { - if (cas_index != 0) - cas_index++; - cas_4_0_available = FALSE; - } - - if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && - (cycle_time_ns_x_100[cas_index] != 0)) { - max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, - cycle_time_ns_x_100[cas_index]); - cas_index++; - } else { - if (cas_index != 0) - cas_index++; - cas_3_0_available = FALSE; - } - } - } - } - - /*------------------------------------------------------------------ - * Set the SDRAM mode, SDRAM_MMODE - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_MMODE, mmode); - mmode = mmode & ~(SDRAM_MMODE_WR_MASK | SDRAM_MMODE_DCL_MASK); - - /* add 10 here because of rounding problems */ - cycle_2_0_clk = MULDIV64(ONE_BILLION, 100, max_2_0_tcyc_ns_x_100) + 10; - cycle_2_5_clk = MULDIV64(ONE_BILLION, 100, max_2_5_tcyc_ns_x_100) + 10; - cycle_3_0_clk = MULDIV64(ONE_BILLION, 100, max_3_0_tcyc_ns_x_100) + 10; - cycle_4_0_clk = MULDIV64(ONE_BILLION, 100, max_4_0_tcyc_ns_x_100) + 10; - cycle_5_0_clk = MULDIV64(ONE_BILLION, 100, max_5_0_tcyc_ns_x_100) + 10; - debug("cycle_3_0_clk=%lu\n", cycle_3_0_clk); - debug("cycle_4_0_clk=%lu\n", cycle_4_0_clk); - debug("cycle_5_0_clk=%lu\n", cycle_5_0_clk); - - if (sdram_ddr1 == TRUE) { /* DDR1 */ - if ((cas_2_0_available == TRUE) && (sdram_freq <= cycle_2_0_clk)) { - mmode |= SDRAM_MMODE_DCL_DDR1_2_0_CLK; - *selected_cas = DDR_CAS_2; - } else if ((cas_2_5_available == TRUE) && (sdram_freq <= cycle_2_5_clk)) { - mmode |= SDRAM_MMODE_DCL_DDR1_2_5_CLK; - *selected_cas = DDR_CAS_2_5; - } else if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) { - mmode |= SDRAM_MMODE_DCL_DDR1_3_0_CLK; - *selected_cas = DDR_CAS_3; - } else { - printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n"); - printf("Only DIMMs DDR1 with CAS latencies of 2.0, 2.5, and 3.0 are supported.\n"); - printf("Make sure the PLB speed is within the supported range of the DIMMs.\n\n"); - spd_ddr_init_hang (); - } - } else { /* DDR2 */ - debug("cas_3_0_available=%d\n", cas_3_0_available); - debug("cas_4_0_available=%d\n", cas_4_0_available); - debug("cas_5_0_available=%d\n", cas_5_0_available); - if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) { - mmode |= SDRAM_MMODE_DCL_DDR2_3_0_CLK; - *selected_cas = DDR_CAS_3; - } else if ((cas_4_0_available == TRUE) && (sdram_freq <= cycle_4_0_clk)) { - mmode |= SDRAM_MMODE_DCL_DDR2_4_0_CLK; - *selected_cas = DDR_CAS_4; - } else if ((cas_5_0_available == TRUE) && (sdram_freq <= cycle_5_0_clk)) { - mmode |= SDRAM_MMODE_DCL_DDR2_5_0_CLK; - *selected_cas = DDR_CAS_5; - } else { - printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n"); - printf("Only DIMMs DDR2 with CAS latencies of 3.0, 4.0, and 5.0 are supported.\n"); - printf("Make sure the PLB speed is within the supported range of the DIMMs.\n"); - printf("cas3=%d cas4=%d cas5=%d\n", - cas_3_0_available, cas_4_0_available, cas_5_0_available); - printf("sdram_freq=%lu cycle3=%lu cycle4=%lu cycle5=%lu\n\n", - sdram_freq, cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk); - spd_ddr_init_hang (); - } - } - - if (sdram_ddr1 == TRUE) - mmode |= SDRAM_MMODE_WR_DDR1; - else { - - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_populated[dimm_num] != SDRAM_NONE) - t_wr_ns = max(t_wr_ns, - spd_read(iic0_dimm_addr[dimm_num], 36) >> 2); - } - - /* - * convert from nanoseconds to ddr clocks - * round up if necessary - */ - t_wr_clk = MULDIV64(sdram_freq, t_wr_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_wr_clk, t_wr_ns); - if (sdram_freq != ddr_check) - t_wr_clk++; - - switch (t_wr_clk) { - case 0: - case 1: - case 2: - case 3: - mmode |= SDRAM_MMODE_WR_DDR2_3_CYC; - break; - case 4: - mmode |= SDRAM_MMODE_WR_DDR2_4_CYC; - break; - case 5: - mmode |= SDRAM_MMODE_WR_DDR2_5_CYC; - break; - default: - mmode |= SDRAM_MMODE_WR_DDR2_6_CYC; - break; - } - *write_recovery = t_wr_clk; - } - - debug("CAS latency = %d\n", *selected_cas); - debug("Write recovery = %d\n", *write_recovery); - - mtsdram(SDRAM_MMODE, mmode); -} - -/*-----------------------------------------------------------------------------+ - * program_rtr. - *-----------------------------------------------------------------------------*/ -static void program_rtr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - PPC4xx_SYS_INFO board_cfg; - unsigned long max_refresh_rate; - unsigned long dimm_num; - unsigned long refresh_rate_type; - unsigned long refresh_rate; - unsigned long rint; - unsigned long sdram_freq; - unsigned long sdr_ddrpll; - unsigned long val; - - /*------------------------------------------------------------------ - * Get the board configuration info. - *-----------------------------------------------------------------*/ - get_sys_info(&board_cfg); - - /*------------------------------------------------------------------ - * Set the SDRAM Refresh Timing Register, SDRAM_RTR - *-----------------------------------------------------------------*/ - mfsdr(SDR0_DDR0, sdr_ddrpll); - sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); - - max_refresh_rate = 0; - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] != SDRAM_NONE) { - - refresh_rate_type = spd_read(iic0_dimm_addr[dimm_num], 12); - refresh_rate_type &= 0x7F; - switch (refresh_rate_type) { - case 0: - refresh_rate = 15625; - break; - case 1: - refresh_rate = 3906; - break; - case 2: - refresh_rate = 7812; - break; - case 3: - refresh_rate = 31250; - break; - case 4: - refresh_rate = 62500; - break; - case 5: - refresh_rate = 125000; - break; - default: - refresh_rate = 0; - printf("ERROR: DIMM %d unsupported refresh rate/type.\n", - (unsigned int)dimm_num); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - break; - } - - max_refresh_rate = max(max_refresh_rate, refresh_rate); - } - } - - rint = MULDIV64(sdram_freq, max_refresh_rate, ONE_BILLION); - mfsdram(SDRAM_RTR, val); - mtsdram(SDRAM_RTR, (val & ~SDRAM_RTR_RINT_MASK) | - (SDRAM_RTR_RINT_ENCODE(rint))); -} - -/*------------------------------------------------------------------ - * This routine programs the SDRAM_TRx registers. - *-----------------------------------------------------------------*/ -static void program_tr(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long sdram_ddr1; - unsigned long t_rp_ns; - unsigned long t_rcd_ns; - unsigned long t_rrd_ns; - unsigned long t_ras_ns; - unsigned long t_rc_ns; - unsigned long t_rfc_ns; - unsigned long t_wpc_ns; - unsigned long t_wtr_ns; - unsigned long t_rpc_ns; - unsigned long t_rp_clk; - unsigned long t_rcd_clk; - unsigned long t_rrd_clk; - unsigned long t_ras_clk; - unsigned long t_rc_clk; - unsigned long t_rfc_clk; - unsigned long t_wpc_clk; - unsigned long t_wtr_clk; - unsigned long t_rpc_clk; - unsigned long sdtr1, sdtr2, sdtr3; - unsigned long ddr_check; - unsigned long sdram_freq; - unsigned long sdr_ddrpll; - - PPC4xx_SYS_INFO board_cfg; - - /*------------------------------------------------------------------ - * Get the board configuration info. - *-----------------------------------------------------------------*/ - get_sys_info(&board_cfg); - - mfsdr(SDR0_DDR0, sdr_ddrpll); - sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); - - /*------------------------------------------------------------------ - * Handle the timing. We need to find the worst case timing of all - * the dimm modules installed. - *-----------------------------------------------------------------*/ - t_rp_ns = 0; - t_rrd_ns = 0; - t_rcd_ns = 0; - t_ras_ns = 0; - t_rc_ns = 0; - t_rfc_ns = 0; - t_wpc_ns = 0; - t_wtr_ns = 0; - t_rpc_ns = 0; - sdram_ddr1 = TRUE; - - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_populated[dimm_num] != SDRAM_NONE) { - if (dimm_populated[dimm_num] == SDRAM_DDR2) - sdram_ddr1 = TRUE; - else - sdram_ddr1 = FALSE; - - t_rcd_ns = max(t_rcd_ns, spd_read(iic0_dimm_addr[dimm_num], 29) >> 2); - t_rrd_ns = max(t_rrd_ns, spd_read(iic0_dimm_addr[dimm_num], 28) >> 2); - t_rp_ns = max(t_rp_ns, spd_read(iic0_dimm_addr[dimm_num], 27) >> 2); - t_ras_ns = max(t_ras_ns, spd_read(iic0_dimm_addr[dimm_num], 30)); - t_rc_ns = max(t_rc_ns, spd_read(iic0_dimm_addr[dimm_num], 41)); - t_rfc_ns = max(t_rfc_ns, spd_read(iic0_dimm_addr[dimm_num], 42)); - } - } - - /*------------------------------------------------------------------ - * Set the SDRAM Timing Reg 1, SDRAM_TR1 - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_SDTR1, sdtr1); - sdtr1 &= ~(SDRAM_SDTR1_LDOF_MASK | SDRAM_SDTR1_RTW_MASK | - SDRAM_SDTR1_WTWO_MASK | SDRAM_SDTR1_RTRO_MASK); - - /* default values */ - sdtr1 |= SDRAM_SDTR1_LDOF_2_CLK; - sdtr1 |= SDRAM_SDTR1_RTW_2_CLK; - - /* normal operations */ - sdtr1 |= SDRAM_SDTR1_WTWO_0_CLK; - sdtr1 |= SDRAM_SDTR1_RTRO_1_CLK; - - mtsdram(SDRAM_SDTR1, sdtr1); - - /*------------------------------------------------------------------ - * Set the SDRAM Timing Reg 2, SDRAM_TR2 - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_SDTR2, sdtr2); - sdtr2 &= ~(SDRAM_SDTR2_RCD_MASK | SDRAM_SDTR2_WTR_MASK | - SDRAM_SDTR2_XSNR_MASK | SDRAM_SDTR2_WPC_MASK | - SDRAM_SDTR2_RPC_MASK | SDRAM_SDTR2_RP_MASK | - SDRAM_SDTR2_RRD_MASK); - - /* - * convert t_rcd from nanoseconds to ddr clocks - * round up if necessary - */ - t_rcd_clk = MULDIV64(sdram_freq, t_rcd_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_rcd_clk, t_rcd_ns); - if (sdram_freq != ddr_check) - t_rcd_clk++; - - switch (t_rcd_clk) { - case 0: - case 1: - sdtr2 |= SDRAM_SDTR2_RCD_1_CLK; - break; - case 2: - sdtr2 |= SDRAM_SDTR2_RCD_2_CLK; - break; - case 3: - sdtr2 |= SDRAM_SDTR2_RCD_3_CLK; - break; - case 4: - sdtr2 |= SDRAM_SDTR2_RCD_4_CLK; - break; - default: - sdtr2 |= SDRAM_SDTR2_RCD_5_CLK; - break; - } - - if (sdram_ddr1 == TRUE) { /* DDR1 */ - if (sdram_freq < 200000000) { - sdtr2 |= SDRAM_SDTR2_WTR_1_CLK; - sdtr2 |= SDRAM_SDTR2_WPC_2_CLK; - sdtr2 |= SDRAM_SDTR2_RPC_2_CLK; - } else { - sdtr2 |= SDRAM_SDTR2_WTR_2_CLK; - sdtr2 |= SDRAM_SDTR2_WPC_3_CLK; - sdtr2 |= SDRAM_SDTR2_RPC_2_CLK; - } - } else { /* DDR2 */ - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_populated[dimm_num] != SDRAM_NONE) { - t_wpc_ns = max(t_wtr_ns, spd_read(iic0_dimm_addr[dimm_num], 36) >> 2); - t_wtr_ns = max(t_wtr_ns, spd_read(iic0_dimm_addr[dimm_num], 37) >> 2); - t_rpc_ns = max(t_rpc_ns, spd_read(iic0_dimm_addr[dimm_num], 38) >> 2); - } - } - - /* - * convert from nanoseconds to ddr clocks - * round up if necessary - */ - t_wpc_clk = MULDIV64(sdram_freq, t_wpc_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_wpc_clk, t_wpc_ns); - if (sdram_freq != ddr_check) - t_wpc_clk++; - - switch (t_wpc_clk) { - case 0: - case 1: - case 2: - sdtr2 |= SDRAM_SDTR2_WPC_2_CLK; - break; - case 3: - sdtr2 |= SDRAM_SDTR2_WPC_3_CLK; - break; - case 4: - sdtr2 |= SDRAM_SDTR2_WPC_4_CLK; - break; - case 5: - sdtr2 |= SDRAM_SDTR2_WPC_5_CLK; - break; - default: - sdtr2 |= SDRAM_SDTR2_WPC_6_CLK; - break; - } - - /* - * convert from nanoseconds to ddr clocks - * round up if necessary - */ - t_wtr_clk = MULDIV64(sdram_freq, t_wtr_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_wtr_clk, t_wtr_ns); - if (sdram_freq != ddr_check) - t_wtr_clk++; - - switch (t_wtr_clk) { - case 0: - case 1: - sdtr2 |= SDRAM_SDTR2_WTR_1_CLK; - break; - case 2: - sdtr2 |= SDRAM_SDTR2_WTR_2_CLK; - break; - case 3: - sdtr2 |= SDRAM_SDTR2_WTR_3_CLK; - break; - default: - sdtr2 |= SDRAM_SDTR2_WTR_4_CLK; - break; - } - - /* - * convert from nanoseconds to ddr clocks - * round up if necessary - */ - t_rpc_clk = MULDIV64(sdram_freq, t_rpc_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_rpc_clk, t_rpc_ns); - if (sdram_freq != ddr_check) - t_rpc_clk++; - - switch (t_rpc_clk) { - case 0: - case 1: - case 2: - sdtr2 |= SDRAM_SDTR2_RPC_2_CLK; - break; - case 3: - sdtr2 |= SDRAM_SDTR2_RPC_3_CLK; - break; - default: - sdtr2 |= SDRAM_SDTR2_RPC_4_CLK; - break; - } - } - - /* default value */ - sdtr2 |= SDRAM_SDTR2_XSNR_16_CLK; - - /* - * convert t_rrd from nanoseconds to ddr clocks - * round up if necessary - */ - t_rrd_clk = MULDIV64(sdram_freq, t_rrd_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_rrd_clk, t_rrd_ns); - if (sdram_freq != ddr_check) - t_rrd_clk++; - - if (t_rrd_clk == 3) - sdtr2 |= SDRAM_SDTR2_RRD_3_CLK; - else - sdtr2 |= SDRAM_SDTR2_RRD_2_CLK; - - /* - * convert t_rp from nanoseconds to ddr clocks - * round up if necessary - */ - t_rp_clk = MULDIV64(sdram_freq, t_rp_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_rp_clk, t_rp_ns); - if (sdram_freq != ddr_check) - t_rp_clk++; - - switch (t_rp_clk) { - case 0: - case 1: - case 2: - case 3: - sdtr2 |= SDRAM_SDTR2_RP_3_CLK; - break; - case 4: - sdtr2 |= SDRAM_SDTR2_RP_4_CLK; - break; - case 5: - sdtr2 |= SDRAM_SDTR2_RP_5_CLK; - break; - case 6: - sdtr2 |= SDRAM_SDTR2_RP_6_CLK; - break; - default: - sdtr2 |= SDRAM_SDTR2_RP_7_CLK; - break; - } - - mtsdram(SDRAM_SDTR2, sdtr2); - - /*------------------------------------------------------------------ - * Set the SDRAM Timing Reg 3, SDRAM_TR3 - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_SDTR3, sdtr3); - sdtr3 &= ~(SDRAM_SDTR3_RAS_MASK | SDRAM_SDTR3_RC_MASK | - SDRAM_SDTR3_XCS_MASK | SDRAM_SDTR3_RFC_MASK); - - /* - * convert t_ras from nanoseconds to ddr clocks - * round up if necessary - */ - t_ras_clk = MULDIV64(sdram_freq, t_ras_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_ras_clk, t_ras_ns); - if (sdram_freq != ddr_check) - t_ras_clk++; - - sdtr3 |= SDRAM_SDTR3_RAS_ENCODE(t_ras_clk); - - /* - * convert t_rc from nanoseconds to ddr clocks - * round up if necessary - */ - t_rc_clk = MULDIV64(sdram_freq, t_rc_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_rc_clk, t_rc_ns); - if (sdram_freq != ddr_check) - t_rc_clk++; - - sdtr3 |= SDRAM_SDTR3_RC_ENCODE(t_rc_clk); - - /* default xcs value */ - sdtr3 |= SDRAM_SDTR3_XCS; - - /* - * convert t_rfc from nanoseconds to ddr clocks - * round up if necessary - */ - t_rfc_clk = MULDIV64(sdram_freq, t_rfc_ns, ONE_BILLION); - ddr_check = MULDIV64(ONE_BILLION, t_rfc_clk, t_rfc_ns); - if (sdram_freq != ddr_check) - t_rfc_clk++; - - sdtr3 |= SDRAM_SDTR3_RFC_ENCODE(t_rfc_clk); - - mtsdram(SDRAM_SDTR3, sdtr3); -} - -/*-----------------------------------------------------------------------------+ - * program_bxcf. - *-----------------------------------------------------------------------------*/ -static void program_bxcf(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long num_col_addr; - unsigned long num_ranks; - unsigned long num_banks; - unsigned long mode; - unsigned long ind_rank; - unsigned long ind; - unsigned long ind_bank; - unsigned long bank_0_populated; - - /*------------------------------------------------------------------ - * Set the BxCF regs. First, wipe out the bank config registers. - *-----------------------------------------------------------------*/ - mtsdram(SDRAM_MB0CF, 0x00000000); - mtsdram(SDRAM_MB1CF, 0x00000000); - mtsdram(SDRAM_MB2CF, 0x00000000); - mtsdram(SDRAM_MB3CF, 0x00000000); - - mode = SDRAM_BXCF_M_BE_ENABLE; - - bank_0_populated = 0; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] != SDRAM_NONE) { - num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4); - num_ranks = spd_read(iic0_dimm_addr[dimm_num], 5); - if ((spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) - num_ranks = (num_ranks & 0x0F) +1; - else - num_ranks = num_ranks & 0x0F; - - num_banks = spd_read(iic0_dimm_addr[dimm_num], 17); - - for (ind_bank = 0; ind_bank < 2; ind_bank++) { - if (num_banks == 4) - ind = 0; - else - ind = 5 << 8; - switch (num_col_addr) { - case 0x08: - mode |= (SDRAM_BXCF_M_AM_0 + ind); - break; - case 0x09: - mode |= (SDRAM_BXCF_M_AM_1 + ind); - break; - case 0x0A: - mode |= (SDRAM_BXCF_M_AM_2 + ind); - break; - case 0x0B: - mode |= (SDRAM_BXCF_M_AM_3 + ind); - break; - case 0x0C: - mode |= (SDRAM_BXCF_M_AM_4 + ind); - break; - default: - printf("DDR-SDRAM: DIMM %d BxCF configuration.\n", - (unsigned int)dimm_num); - printf("ERROR: Unsupported value for number of " - "column addresses: %d.\n", (unsigned int)num_col_addr); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - } - } - - if ((dimm_populated[dimm_num] != SDRAM_NONE)&& (dimm_num ==1)) - bank_0_populated = 1; - - for (ind_rank = 0; ind_rank < num_ranks; ind_rank++) { - mtsdram(SDRAM_MB0CF + - ((dimm_num + bank_0_populated + ind_rank) << 2), - mode); - } - } - } -} - -/*------------------------------------------------------------------ - * program memory queue. - *-----------------------------------------------------------------*/ -static void program_memory_queue(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - phys_size_t rank_base_addr; - unsigned long rank_reg; - phys_size_t rank_size_bytes; - unsigned long rank_size_id; - unsigned long num_ranks; - unsigned long baseadd_size; - unsigned long i; - unsigned long bank_0_populated = 0; - phys_size_t total_size = 0; - - /*------------------------------------------------------------------ - * Reset the rank_base_address. - *-----------------------------------------------------------------*/ - rank_reg = SDRAM_R0BAS; - - rank_base_addr = 0x00000000; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_populated[dimm_num] != SDRAM_NONE) { - num_ranks = spd_read(iic0_dimm_addr[dimm_num], 5); - if ((spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) - num_ranks = (num_ranks & 0x0F) + 1; - else - num_ranks = num_ranks & 0x0F; - - rank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31); - - /*------------------------------------------------------------------ - * Set the sizes - *-----------------------------------------------------------------*/ - baseadd_size = 0; - switch (rank_size_id) { - case 0x01: - baseadd_size |= SDRAM_RXBAS_SDSZ_1024; - total_size = 1024; - break; - case 0x02: - baseadd_size |= SDRAM_RXBAS_SDSZ_2048; - total_size = 2048; - break; - case 0x04: - baseadd_size |= SDRAM_RXBAS_SDSZ_4096; - total_size = 4096; - break; - case 0x08: - baseadd_size |= SDRAM_RXBAS_SDSZ_32; - total_size = 32; - break; - case 0x10: - baseadd_size |= SDRAM_RXBAS_SDSZ_64; - total_size = 64; - break; - case 0x20: - baseadd_size |= SDRAM_RXBAS_SDSZ_128; - total_size = 128; - break; - case 0x40: - baseadd_size |= SDRAM_RXBAS_SDSZ_256; - total_size = 256; - break; - case 0x80: - baseadd_size |= SDRAM_RXBAS_SDSZ_512; - total_size = 512; - break; - default: - printf("DDR-SDRAM: DIMM %d memory queue configuration.\n", - (unsigned int)dimm_num); - printf("ERROR: Unsupported value for the banksize: %d.\n", - (unsigned int)rank_size_id); - printf("Replace the DIMM module with a supported DIMM.\n\n"); - spd_ddr_init_hang (); - } - rank_size_bytes = total_size << 20; - - if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1)) - bank_0_populated = 1; - - for (i = 0; i < num_ranks; i++) { - mtdcr_any(rank_reg+i+dimm_num+bank_0_populated, - (SDRAM_RXBAS_SDBA_ENCODE(rank_base_addr) | - baseadd_size)); - rank_base_addr += rank_size_bytes; - } - } - } - -#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ - defined(CONFIG_460SX) - /* - * Enable high bandwidth access - * This is currently not used, but with this setup - * it is possible to use it later on in e.g. the Linux - * EMAC driver for performance gain. - */ - mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */ - mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */ - - /* - * Set optimal value for Memory Queue HB/LL Configuration registers - */ - mtdcr(SDRAM_CONF1HB, (mfdcr(SDRAM_CONF1HB) & ~SDRAM_CONF1HB_MASK) | - SDRAM_CONF1HB_AAFR | SDRAM_CONF1HB_RPEN | SDRAM_CONF1HB_RFTE | - SDRAM_CONF1HB_RPLM | SDRAM_CONF1HB_WRCL); - mtdcr(SDRAM_CONF1LL, (mfdcr(SDRAM_CONF1LL) & ~SDRAM_CONF1LL_MASK) | - SDRAM_CONF1LL_AAFR | SDRAM_CONF1LL_RPEN | SDRAM_CONF1LL_RFTE | - SDRAM_CONF1LL_RPLM); - mtdcr(SDRAM_CONFPATHB, mfdcr(SDRAM_CONFPATHB) | SDRAM_CONFPATHB_TPEN); -#endif -} - -#ifdef CONFIG_DDR_ECC -/*-----------------------------------------------------------------------------+ - * program_ecc. - *-----------------------------------------------------------------------------*/ -static void program_ecc(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks, - unsigned long tlb_word2_i_value) -{ - unsigned long dimm_num; - unsigned long ecc; - - ecc = 0; - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_populated[dimm_num] != SDRAM_NONE) - ecc = max(ecc, spd_read(iic0_dimm_addr[dimm_num], 11)); - } - if (ecc == 0) - return; - - do_program_ecc(tlb_word2_i_value); -} -#endif - -#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) -/*-----------------------------------------------------------------------------+ - * program_DQS_calibration. - *-----------------------------------------------------------------------------*/ -static void program_DQS_calibration(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks) -{ - unsigned long val; - -#ifdef HARD_CODED_DQS /* calibration test with hardvalues */ - mtsdram(SDRAM_RQDC, 0x80000037); - mtsdram(SDRAM_RDCC, 0x40000000); - mtsdram(SDRAM_RFDC, 0x000001DF); - - test(); -#else - /*------------------------------------------------------------------ - * Program RDCC register - * Read sample cycle auto-update enable - *-----------------------------------------------------------------*/ - - mfsdram(SDRAM_RDCC, val); - mtsdram(SDRAM_RDCC, - (val & ~(SDRAM_RDCC_RDSS_MASK | SDRAM_RDCC_RSAE_MASK)) - | SDRAM_RDCC_RSAE_ENABLE); - - /*------------------------------------------------------------------ - * Program RQDC register - * Internal DQS delay mechanism enable - *-----------------------------------------------------------------*/ - mtsdram(SDRAM_RQDC, (SDRAM_RQDC_RQDE_ENABLE|SDRAM_RQDC_RQFD_ENCODE(0x38))); - - /*------------------------------------------------------------------ - * Program RFDC register - * Set Feedback Fractional Oversample - * Auto-detect read sample cycle enable - * Set RFOS to 1/4 of memclk cycle (0x3f) - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_RFDC, val); - mtsdram(SDRAM_RFDC, - (val & ~(SDRAM_RFDC_ARSE_MASK | SDRAM_RFDC_RFOS_MASK | - SDRAM_RFDC_RFFD_MASK)) - | (SDRAM_RFDC_ARSE_ENABLE | SDRAM_RFDC_RFOS_ENCODE(0x3f) | - SDRAM_RFDC_RFFD_ENCODE(0))); - - DQS_calibration_process(); -#endif -} - -static int short_mem_test(void) -{ - u32 *membase; - u32 bxcr_num; - u32 bxcf; - int i; - int j; - phys_size_t base_addr; - u32 test[NUMMEMTESTS][NUMMEMWORDS] = { - {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, - {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}, - {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555}, - {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA}, - {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A}, - {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5}, - {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA}, - {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} }; - int l; - - for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { - mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf); - - /* Banks enabled */ - if ((bxcf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) { - /* Bank is enabled */ - - /* - * Only run test on accessable memory (below 2GB) - */ - base_addr = SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)); - if (base_addr >= CONFIG_MAX_MEM_MAPPED) - continue; - - /*------------------------------------------------------------------ - * Run the short memory test. - *-----------------------------------------------------------------*/ - membase = (u32 *)(u32)base_addr; - - for (i = 0; i < NUMMEMTESTS; i++) { - for (j = 0; j < NUMMEMWORDS; j++) { - membase[j] = test[i][j]; - ppcDcbf((u32)&(membase[j])); - } - sync(); - for (l=0; l<NUMLOOPS; l++) { - for (j = 0; j < NUMMEMWORDS; j++) { - if (membase[j] != test[i][j]) { - ppcDcbf((u32)&(membase[j])); - return 0; - } - ppcDcbf((u32)&(membase[j])); - } - sync(); - } - } - } /* if bank enabled */ - } /* for bxcf_num */ - - return 1; -} - -#ifndef HARD_CODED_DQS -/*-----------------------------------------------------------------------------+ - * DQS_calibration_process. - *-----------------------------------------------------------------------------*/ -static void DQS_calibration_process(void) -{ - unsigned long rfdc_reg; - unsigned long rffd; - unsigned long val; - long rffd_average; - long max_start; - long min_end; - unsigned long begin_rqfd[MAXRANKS]; - unsigned long begin_rffd[MAXRANKS]; - unsigned long end_rqfd[MAXRANKS]; - unsigned long end_rffd[MAXRANKS]; - char window_found; - unsigned long dlycal; - unsigned long dly_val; - unsigned long max_pass_length; - unsigned long current_pass_length; - unsigned long current_fail_length; - unsigned long current_start; - long max_end; - unsigned char fail_found; - unsigned char pass_found; -#if !defined(CONFIG_DDR_RQDC_FIXED) - u32 rqdc_reg; - u32 rqfd; - u32 rqfd_start; - u32 rqfd_average; - int loopi = 0; - char str[] = "Auto calibration -"; - char slash[] = "\\|/-\\|/-"; - - /*------------------------------------------------------------------ - * Test to determine the best read clock delay tuning bits. - * - * Before the DDR controller can be used, the read clock delay needs to be - * set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD]. - * This value cannot be hardcoded into the program because it changes - * depending on the board's setup and environment. - * To do this, all delay values are tested to see if they - * work or not. By doing this, you get groups of fails with groups of - * passing values. The idea is to find the start and end of a passing - * window and take the center of it to use as the read clock delay. - * - * A failure has to be seen first so that when we hit a pass, we know - * that it is truely the start of the window. If we get passing values - * to start off with, we don't know if we are at the start of the window. - * - * The code assumes that a failure will always be found. - * If a failure is not found, there is no easy way to get the middle - * of the passing window. I guess we can pretty much pick any value - * but some values will be better than others. Since the lowest speed - * we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed), - * from experimentation it is safe to say you will always have a failure. - *-----------------------------------------------------------------*/ - - /* first fix RQDC[RQFD] to an average of 80 degre phase shift to find RFDC[RFFD] */ - rqfd_start = 64; /* test-only: don't know if this is the _best_ start value */ - - puts(str); - -calibration_loop: - mfsdram(SDRAM_RQDC, rqdc_reg); - mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | - SDRAM_RQDC_RQFD_ENCODE(rqfd_start)); -#else /* CONFIG_DDR_RQDC_FIXED */ - /* - * On Katmai the complete auto-calibration somehow doesn't seem to - * produce the best results, meaning optimal values for RQFD/RFFD. - * This was discovered by GDA using a high bandwidth scope, - * analyzing the DDR2 signals. GDA provided a fixed value for RQFD, - * so now on Katmai "only" RFFD is auto-calibrated. - */ - mtsdram(SDRAM_RQDC, CONFIG_DDR_RQDC_FIXED); -#endif /* CONFIG_DDR_RQDC_FIXED */ - - max_start = 0; - min_end = 0; - begin_rqfd[0] = 0; - begin_rffd[0] = 0; - begin_rqfd[1] = 0; - begin_rffd[1] = 0; - end_rqfd[0] = 0; - end_rffd[0] = 0; - end_rqfd[1] = 0; - end_rffd[1] = 0; - window_found = FALSE; - - max_pass_length = 0; - max_start = 0; - max_end = 0; - current_pass_length = 0; - current_fail_length = 0; - current_start = 0; - window_found = FALSE; - fail_found = FALSE; - pass_found = FALSE; - - /* - * get the delay line calibration register value - */ - mfsdram(SDRAM_DLCR, dlycal); - dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2; - - for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) { - mfsdram(SDRAM_RFDC, rfdc_reg); - rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); - - /*------------------------------------------------------------------ - * Set the timing reg for the test. - *-----------------------------------------------------------------*/ - mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd)); - - /*------------------------------------------------------------------ - * See if the rffd value passed. - *-----------------------------------------------------------------*/ - if (short_mem_test()) { - if (fail_found == TRUE) { - pass_found = TRUE; - if (current_pass_length == 0) - current_start = rffd; - - current_fail_length = 0; - current_pass_length++; - - if (current_pass_length > max_pass_length) { - max_pass_length = current_pass_length; - max_start = current_start; - max_end = rffd; - } - } - } else { - current_pass_length = 0; - current_fail_length++; - - if (current_fail_length >= (dly_val >> 2)) { - if (fail_found == FALSE) { - fail_found = TRUE; - } else if (pass_found == TRUE) { - window_found = TRUE; - break; - } - } - } - } /* for rffd */ - - /*------------------------------------------------------------------ - * Set the average RFFD value - *-----------------------------------------------------------------*/ - rffd_average = ((max_start + max_end) >> 1); - - if (rffd_average < 0) - rffd_average = 0; - - if (rffd_average > SDRAM_RFDC_RFFD_MAX) - rffd_average = SDRAM_RFDC_RFFD_MAX; - /* now fix RFDC[RFFD] found and find RQDC[RQFD] */ - mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average)); - -#if !defined(CONFIG_DDR_RQDC_FIXED) - max_pass_length = 0; - max_start = 0; - max_end = 0; - current_pass_length = 0; - current_fail_length = 0; - current_start = 0; - window_found = FALSE; - fail_found = FALSE; - pass_found = FALSE; - - for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) { - mfsdram(SDRAM_RQDC, rqdc_reg); - rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); - - /*------------------------------------------------------------------ - * Set the timing reg for the test. - *-----------------------------------------------------------------*/ - mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd)); - - /*------------------------------------------------------------------ - * See if the rffd value passed. - *-----------------------------------------------------------------*/ - if (short_mem_test()) { - if (fail_found == TRUE) { - pass_found = TRUE; - if (current_pass_length == 0) - current_start = rqfd; - - current_fail_length = 0; - current_pass_length++; - - if (current_pass_length > max_pass_length) { - max_pass_length = current_pass_length; - max_start = current_start; - max_end = rqfd; - } - } - } else { - current_pass_length = 0; - current_fail_length++; - - if (fail_found == FALSE) { - fail_found = TRUE; - } else if (pass_found == TRUE) { - window_found = TRUE; - break; - } - } - } - - rqfd_average = ((max_start + max_end) >> 1); - - /*------------------------------------------------------------------ - * Make sure we found the valid read passing window. Halt if not - *-----------------------------------------------------------------*/ - if (window_found == FALSE) { - if (rqfd_start < SDRAM_RQDC_RQFD_MAX) { - putc('\b'); - putc(slash[loopi++ % 8]); - - /* try again from with a different RQFD start value */ - rqfd_start++; - goto calibration_loop; - } - - printf("\nERROR: Cannot determine a common read delay for the " - "DIMM(s) installed.\n"); - debug("%s[%d] ERROR : \n", __FUNCTION__,__LINE__); - ppc4xx_ibm_ddr2_register_dump(); - spd_ddr_init_hang (); - } - - if (rqfd_average < 0) - rqfd_average = 0; - - if (rqfd_average > SDRAM_RQDC_RQFD_MAX) - rqfd_average = SDRAM_RQDC_RQFD_MAX; - - mtsdram(SDRAM_RQDC, - (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | - SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); - - blank_string(strlen(str)); -#endif /* CONFIG_DDR_RQDC_FIXED */ - - mfsdram(SDRAM_DLCR, val); - debug("%s[%d] DLCR: 0x%08lX\n", __FUNCTION__, __LINE__, val); - mfsdram(SDRAM_RQDC, val); - debug("%s[%d] RQDC: 0x%08lX\n", __FUNCTION__, __LINE__, val); - mfsdram(SDRAM_RFDC, val); - debug("%s[%d] RFDC: 0x%08lX\n", __FUNCTION__, __LINE__, val); - mfsdram(SDRAM_RDCC, val); - debug("%s[%d] RDCC: 0x%08lX\n", __FUNCTION__, __LINE__, val); -} -#else /* calibration test with hardvalues */ -/*-----------------------------------------------------------------------------+ - * DQS_calibration_process. - *-----------------------------------------------------------------------------*/ -static void test(void) -{ - unsigned long dimm_num; - unsigned long ecc_temp; - unsigned long i, j; - unsigned long *membase; - unsigned long bxcf[MAXRANKS]; - unsigned long val; - char window_found; - char begin_found[MAXDIMMS]; - char end_found[MAXDIMMS]; - char search_end[MAXDIMMS]; - unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = { - {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, - {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}, - {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555}, - {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA}, - {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A}, - {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5}, - {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA}, - {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} }; - - /*------------------------------------------------------------------ - * Test to determine the best read clock delay tuning bits. - * - * Before the DDR controller can be used, the read clock delay needs to be - * set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD]. - * This value cannot be hardcoded into the program because it changes - * depending on the board's setup and environment. - * To do this, all delay values are tested to see if they - * work or not. By doing this, you get groups of fails with groups of - * passing values. The idea is to find the start and end of a passing - * window and take the center of it to use as the read clock delay. - * - * A failure has to be seen first so that when we hit a pass, we know - * that it is truely the start of the window. If we get passing values - * to start off with, we don't know if we are at the start of the window. - * - * The code assumes that a failure will always be found. - * If a failure is not found, there is no easy way to get the middle - * of the passing window. I guess we can pretty much pick any value - * but some values will be better than others. Since the lowest speed - * we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed), - * from experimentation it is safe to say you will always have a failure. - *-----------------------------------------------------------------*/ - mfsdram(SDRAM_MCOPT1, ecc_temp); - ecc_temp &= SDRAM_MCOPT1_MCHK_MASK; - mfsdram(SDRAM_MCOPT1, val); - mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) | - SDRAM_MCOPT1_MCHK_NON); - - window_found = FALSE; - begin_found[0] = FALSE; - end_found[0] = FALSE; - search_end[0] = FALSE; - begin_found[1] = FALSE; - end_found[1] = FALSE; - search_end[1] = FALSE; - - for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) { - mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf[bxcr_num]); - - /* Banks enabled */ - if ((bxcf[dimm_num] & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) { - - /* Bank is enabled */ - membase = - (unsigned long*)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+dimm_num))); - - /*------------------------------------------------------------------ - * Run the short memory test. - *-----------------------------------------------------------------*/ - for (i = 0; i < NUMMEMTESTS; i++) { - for (j = 0; j < NUMMEMWORDS; j++) { - membase[j] = test[i][j]; - ppcDcbf((u32)&(membase[j])); - } - sync(); - for (j = 0; j < NUMMEMWORDS; j++) { - if (membase[j] != test[i][j]) { - ppcDcbf((u32)&(membase[j])); - break; - } - ppcDcbf((u32)&(membase[j])); - } - sync(); - if (j < NUMMEMWORDS) - break; - } - - /*------------------------------------------------------------------ - * See if the rffd value passed. - *-----------------------------------------------------------------*/ - if (i < NUMMEMTESTS) { - if ((end_found[dimm_num] == FALSE) && - (search_end[dimm_num] == TRUE)) { - end_found[dimm_num] = TRUE; - } - if ((end_found[0] == TRUE) && - (end_found[1] == TRUE)) - break; - } else { - if (begin_found[dimm_num] == FALSE) { - begin_found[dimm_num] = TRUE; - search_end[dimm_num] = TRUE; - } - } - } else { - begin_found[dimm_num] = TRUE; - end_found[dimm_num] = TRUE; - } - } - - if ((begin_found[0] == TRUE) && (begin_found[1] == TRUE)) - window_found = TRUE; - - /*------------------------------------------------------------------ - * Make sure we found the valid read passing window. Halt if not - *-----------------------------------------------------------------*/ - if (window_found == FALSE) { - printf("ERROR: Cannot determine a common read delay for the " - "DIMM(s) installed.\n"); - spd_ddr_init_hang (); - } - - /*------------------------------------------------------------------ - * Restore the ECC variable to what it originally was - *-----------------------------------------------------------------*/ - mtsdram(SDRAM_MCOPT1, - (ppcMfdcr_sdram(SDRAM_MCOPT1) & ~SDRAM_MCOPT1_MCHK_MASK) - | ecc_temp); -} -#endif /* !HARD_CODED_DQS */ -#endif /* !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */ - -#else /* CONFIG_SPD_EEPROM */ - -/*----------------------------------------------------------------------------- - * Function: initdram - * Description: Configures the PPC4xx IBM DDR1/DDR2 SDRAM memory controller. - * The configuration is performed using static, compile- - * time parameters. - * Configures the PPC405EX(r) and PPC460EX/GT - *---------------------------------------------------------------------------*/ -phys_size_t initdram(int board_type) -{ - /* - * Only run this SDRAM init code once. For NAND booting - * targets like Kilauea, we call initdram() early from the - * 4k NAND booting image (CONFIG_NAND_SPL) from nand_boot(). - * Later on the NAND U-Boot image runs (CONFIG_NAND_U_BOOT) - * which calls initdram() again. This time the controller - * mustn't be reconfigured again since we're already running - * from SDRAM. - */ -#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) - unsigned long val; - -#if defined(CONFIG_440) - mtdcr(SDRAM_R0BAS, CONFIG_SYS_SDRAM_R0BAS); - mtdcr(SDRAM_R1BAS, CONFIG_SYS_SDRAM_R1BAS); - mtdcr(SDRAM_R2BAS, CONFIG_SYS_SDRAM_R2BAS); - mtdcr(SDRAM_R3BAS, CONFIG_SYS_SDRAM_R3BAS); - mtdcr(SDRAM_PLBADDULL, CONFIG_SYS_SDRAM_PLBADDULL); /* MQ0_BAUL */ - mtdcr(SDRAM_PLBADDUHB, CONFIG_SYS_SDRAM_PLBADDUHB); /* MQ0_BAUH */ - mtdcr(SDRAM_CONF1LL, CONFIG_SYS_SDRAM_CONF1LL); - mtdcr(SDRAM_CONF1HB, CONFIG_SYS_SDRAM_CONF1HB); - mtdcr(SDRAM_CONFPATHB, CONFIG_SYS_SDRAM_CONFPATHB); -#endif - - /* Set Memory Bank Configuration Registers */ - - mtsdram(SDRAM_MB0CF, CONFIG_SYS_SDRAM0_MB0CF); - mtsdram(SDRAM_MB1CF, CONFIG_SYS_SDRAM0_MB1CF); - mtsdram(SDRAM_MB2CF, CONFIG_SYS_SDRAM0_MB2CF); - mtsdram(SDRAM_MB3CF, CONFIG_SYS_SDRAM0_MB3CF); - - /* Set Memory Clock Timing Register */ - - mtsdram(SDRAM_CLKTR, CONFIG_SYS_SDRAM0_CLKTR); - - /* Set Refresh Time Register */ - - mtsdram(SDRAM_RTR, CONFIG_SYS_SDRAM0_RTR); - - /* Set SDRAM Timing Registers */ - - mtsdram(SDRAM_SDTR1, CONFIG_SYS_SDRAM0_SDTR1); - mtsdram(SDRAM_SDTR2, CONFIG_SYS_SDRAM0_SDTR2); - mtsdram(SDRAM_SDTR3, CONFIG_SYS_SDRAM0_SDTR3); - - /* Set Mode and Extended Mode Registers */ - - mtsdram(SDRAM_MMODE, CONFIG_SYS_SDRAM0_MMODE); - mtsdram(SDRAM_MEMODE, CONFIG_SYS_SDRAM0_MEMODE); - - /* Set Memory Controller Options 1 Register */ - - mtsdram(SDRAM_MCOPT1, CONFIG_SYS_SDRAM0_MCOPT1); - - /* Set Manual Initialization Control Registers */ - - mtsdram(SDRAM_INITPLR0, CONFIG_SYS_SDRAM0_INITPLR0); - mtsdram(SDRAM_INITPLR1, CONFIG_SYS_SDRAM0_INITPLR1); - mtsdram(SDRAM_INITPLR2, CONFIG_SYS_SDRAM0_INITPLR2); - mtsdram(SDRAM_INITPLR3, CONFIG_SYS_SDRAM0_INITPLR3); - mtsdram(SDRAM_INITPLR4, CONFIG_SYS_SDRAM0_INITPLR4); - mtsdram(SDRAM_INITPLR5, CONFIG_SYS_SDRAM0_INITPLR5); - mtsdram(SDRAM_INITPLR6, CONFIG_SYS_SDRAM0_INITPLR6); - mtsdram(SDRAM_INITPLR7, CONFIG_SYS_SDRAM0_INITPLR7); - mtsdram(SDRAM_INITPLR8, CONFIG_SYS_SDRAM0_INITPLR8); - mtsdram(SDRAM_INITPLR9, CONFIG_SYS_SDRAM0_INITPLR9); - mtsdram(SDRAM_INITPLR10, CONFIG_SYS_SDRAM0_INITPLR10); - mtsdram(SDRAM_INITPLR11, CONFIG_SYS_SDRAM0_INITPLR11); - mtsdram(SDRAM_INITPLR12, CONFIG_SYS_SDRAM0_INITPLR12); - mtsdram(SDRAM_INITPLR13, CONFIG_SYS_SDRAM0_INITPLR13); - mtsdram(SDRAM_INITPLR14, CONFIG_SYS_SDRAM0_INITPLR14); - mtsdram(SDRAM_INITPLR15, CONFIG_SYS_SDRAM0_INITPLR15); - - /* Set On-Die Termination Registers */ - - mtsdram(SDRAM_CODT, CONFIG_SYS_SDRAM0_CODT); - mtsdram(SDRAM_MODT0, CONFIG_SYS_SDRAM0_MODT0); - mtsdram(SDRAM_MODT1, CONFIG_SYS_SDRAM0_MODT1); - - /* Set Write Timing Register */ - - mtsdram(SDRAM_WRDTR, CONFIG_SYS_SDRAM0_WRDTR); - - /* - * Start Initialization by SDRAM0_MCOPT2[SREN] = 0 and - * SDRAM0_MCOPT2[IPTR] = 1 - */ - - mtsdram(SDRAM_MCOPT2, (SDRAM_MCOPT2_SREN_EXIT | - SDRAM_MCOPT2_IPTR_EXECUTE)); - - /* - * Poll SDRAM0_MCSTAT[MIC] for assertion to indicate the - * completion of initialization. - */ - - do { - mfsdram(SDRAM_MCSTAT, val); - } while ((val & SDRAM_MCSTAT_MIC_MASK) != SDRAM_MCSTAT_MIC_COMP); - - /* Set Delay Control Registers */ - - mtsdram(SDRAM_DLCR, CONFIG_SYS_SDRAM0_DLCR); - -#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) - mtsdram(SDRAM_RDCC, CONFIG_SYS_SDRAM0_RDCC); - mtsdram(SDRAM_RQDC, CONFIG_SYS_SDRAM0_RQDC); - mtsdram(SDRAM_RFDC, CONFIG_SYS_SDRAM0_RFDC); -#endif /* !CONFIG_PPC4xx_DDR_AUTOCALIBRATION */ - - /* - * Enable Controller by SDRAM0_MCOPT2[DCEN] = 1: - */ - - mfsdram(SDRAM_MCOPT2, val); - mtsdram(SDRAM_MCOPT2, val | SDRAM_MCOPT2_DCEN_ENABLE); - -#if defined(CONFIG_440) - /* - * Program TLB entries with caches enabled, for best performace - * while auto-calibrating and ECC generation - */ - program_tlb(0, 0, (CONFIG_SYS_MBYTES_SDRAM << 20), 0); -#endif - -#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) -#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) - /*------------------------------------------------------------------ - | DQS calibration. - +-----------------------------------------------------------------*/ - DQS_autocalibration(); -#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */ -#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */ - - /* - * Now complete RDSS configuration as mentioned on page 7 of the AMCC - * PowerPC440SP/SPe DDR2 application note: - * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning" - */ - update_rdcc(); - -#if defined(CONFIG_DDR_ECC) - do_program_ecc(0); -#endif /* defined(CONFIG_DDR_ECC) */ - -#if defined(CONFIG_440) - /* - * Now after initialization (auto-calibration and ECC generation) - * remove the TLB entries with caches enabled and program again with - * desired cache functionality - */ - remove_tlb(0, (CONFIG_SYS_MBYTES_SDRAM << 20)); - program_tlb(0, 0, (CONFIG_SYS_MBYTES_SDRAM << 20), MY_TLB_WORD2_I_ENABLE); -#endif - - ppc4xx_ibm_ddr2_register_dump(); - -#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) - /* - * Clear potential errors resulting from auto-calibration. - * If not done, then we could get an interrupt later on when - * exceptions are enabled. - */ - set_mcsr(get_mcsr()); -#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */ - -#endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */ - - return (CONFIG_SYS_MBYTES_SDRAM << 20); -} -#endif /* CONFIG_SPD_EEPROM */ - -#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) -#if defined(CONFIG_440) -u32 mfdcr_any(u32 dcr) -{ - u32 val; - - switch (dcr) { - case SDRAM_R0BAS + 0: - val = mfdcr(SDRAM_R0BAS + 0); - break; - case SDRAM_R0BAS + 1: - val = mfdcr(SDRAM_R0BAS + 1); - break; - case SDRAM_R0BAS + 2: - val = mfdcr(SDRAM_R0BAS + 2); - break; - case SDRAM_R0BAS + 3: - val = mfdcr(SDRAM_R0BAS + 3); - break; - default: - printf("DCR %d not defined in case statement!!!\n", dcr); - val = 0; /* just to satisfy the compiler */ - } - - return val; -} - -void mtdcr_any(u32 dcr, u32 val) -{ - switch (dcr) { - case SDRAM_R0BAS + 0: - mtdcr(SDRAM_R0BAS + 0, val); - break; - case SDRAM_R0BAS + 1: - mtdcr(SDRAM_R0BAS + 1, val); - break; - case SDRAM_R0BAS + 2: - mtdcr(SDRAM_R0BAS + 2, val); - break; - case SDRAM_R0BAS + 3: - mtdcr(SDRAM_R0BAS + 3, val); - break; - default: - printf("DCR %d not defined in case statement!!!\n", dcr); - } -} -#endif /* defined(CONFIG_440) */ -#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */ - -inline void ppc4xx_ibm_ddr2_register_dump(void) -{ -#if defined(DEBUG) - printf("\nPPC4xx IBM DDR2 Register Dump:\n"); - -#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT)) - PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R0BAS); - PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R1BAS); - PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R2BAS); - PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R3BAS); -#endif /* (defined(CONFIG_440SP) || ... */ -#if defined(CONFIG_405EX) - PPC4xx_IBM_DDR2_DUMP_REGISTER(BESR); - PPC4xx_IBM_DDR2_DUMP_REGISTER(BEARL); - PPC4xx_IBM_DDR2_DUMP_REGISTER(BEARH); - PPC4xx_IBM_DDR2_DUMP_REGISTER(WMIRQ); - PPC4xx_IBM_DDR2_DUMP_REGISTER(PLBOPT); - PPC4xx_IBM_DDR2_DUMP_REGISTER(PUABA); -#endif /* defined(CONFIG_405EX) */ - PPC4xx_IBM_DDR2_DUMP_REGISTER(MB0CF); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MB1CF); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MB2CF); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MB3CF); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MCSTAT); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MCOPT1); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MCOPT2); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT0); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT1); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT2); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT3); - PPC4xx_IBM_DDR2_DUMP_REGISTER(CODT); -#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT)) - PPC4xx_IBM_DDR2_DUMP_REGISTER(VVPR); - PPC4xx_IBM_DDR2_DUMP_REGISTER(OPARS); - /* - * OPART is only used as a trigger register. - * - * No data is contained in this register, and reading or writing - * to is can cause bad things to happen (hangs). Just skip it and - * report "N/A". - */ - printf("%20s = N/A\n", "SDRAM_OPART"); -#endif /* defined(CONFIG_440SP) || ... */ - PPC4xx_IBM_DDR2_DUMP_REGISTER(RTR); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR0); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR1); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR2); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR3); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR4); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR5); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR6); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR7); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR8); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR9); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR10); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR11); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR12); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR13); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR14); - PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR15); - PPC4xx_IBM_DDR2_DUMP_REGISTER(RQDC); - PPC4xx_IBM_DDR2_DUMP_REGISTER(RFDC); - PPC4xx_IBM_DDR2_DUMP_REGISTER(RDCC); - PPC4xx_IBM_DDR2_DUMP_REGISTER(DLCR); - PPC4xx_IBM_DDR2_DUMP_REGISTER(CLKTR); - PPC4xx_IBM_DDR2_DUMP_REGISTER(WRDTR); - PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR1); - PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR2); - PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR3); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MMODE); - PPC4xx_IBM_DDR2_DUMP_REGISTER(MEMODE); - PPC4xx_IBM_DDR2_DUMP_REGISTER(ECCES); -#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT)) - PPC4xx_IBM_DDR2_DUMP_REGISTER(CID); -#endif /* defined(CONFIG_440SP) || ... */ - PPC4xx_IBM_DDR2_DUMP_REGISTER(RID); - PPC4xx_IBM_DDR2_DUMP_REGISTER(FCSR); - PPC4xx_IBM_DDR2_DUMP_REGISTER(RTSR); -#endif /* defined(DEBUG) */ -} diff --git a/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c deleted file mode 100644 index b909fca..0000000 --- a/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c +++ /dev/null @@ -1,1253 +0,0 @@ -/* - * arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c - * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a - * DDR2 controller (non Denali Core). Those currently are: - * - * 405: 405EX - * 440/460: 440SP/440SPe/460EX/460GT/460SX - * - * (C) Copyright 2008 Applied Micro Circuits Corporation - * Adam Graham <agraham@amcc.com> - * - * (C) Copyright 2007-2008 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * COPYRIGHT AMCC CORPORATION 2004 - * - * 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 - * - */ - -/* define DEBUG for debugging output (obviously ;-)) */ -#undef DEBUG - -#include <common.h> -#include <asm/ppc4xx.h> -#include <asm/io.h> -#include <asm/processor.h> - -#include "ecc.h" - -/* - * Only compile the DDR auto-calibration code for NOR boot and - * not for NAND boot (NAND SPL and NAND U-Boot - NUB) - */ -#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) - -#define MAXBXCF 4 -#define SDRAM_RXBAS_SHIFT_1M 20 - -#if defined(CONFIG_SYS_DECREMENT_PATTERNS) -#define NUMMEMTESTS 24 -#else -#define NUMMEMTESTS 8 -#endif /* CONFIG_SYS_DECREMENT_PATTERNS */ -#define NUMLOOPS 1 /* configure as you deem approporiate */ -#define NUMMEMWORDS 16 - -#define SDRAM_RDCC_RDSS_VAL(n) SDRAM_RDCC_RDSS_DECODE(ddr_rdss_opt(n)) - -/* Private Structure Definitions */ - -struct autocal_regs { - u32 rffd; - u32 rqfd; -}; - -struct ddrautocal { - u32 rffd; - u32 rffd_min; - u32 rffd_max; - u32 rffd_size; - u32 rqfd; - u32 rqfd_size; - u32 rdcc; - u32 flags; -}; - -struct sdram_timing_clks { - u32 wrdtr; - u32 clktr; - u32 rdcc; - u32 flags; -}; - -struct autocal_clks { - struct sdram_timing_clks clocks; - struct ddrautocal autocal; -}; - -/*--------------------------------------------------------------------------+ - * Prototypes - *--------------------------------------------------------------------------*/ -#if defined(CONFIG_PPC4xx_DDR_METHOD_A) -static u32 DQS_calibration_methodA(struct ddrautocal *); -static u32 program_DQS_calibration_methodA(struct ddrautocal *); -#else -static u32 DQS_calibration_methodB(struct ddrautocal *); -static u32 program_DQS_calibration_methodB(struct ddrautocal *); -#endif -static int short_mem_test(u32 *); - -/* - * To provide an interface for board specific config values in this common - * DDR setup code, we implement he "weak" default functions here. They return - * the default value back to the caller. - * - * Please see include/configs/yucca.h for an example fora board specific - * implementation. - */ - -#if !defined(CONFIG_SPD_EEPROM) -u32 __ddr_wrdtr(u32 default_val) -{ - return default_val; -} -u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr"))); - -u32 __ddr_clktr(u32 default_val) -{ - return default_val; -} -u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr"))); - -/* - * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed - */ -void __spd_ddr_init_hang(void) -{ - hang(); -} -void -spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang"))); -#endif /* defined(CONFIG_SPD_EEPROM) */ - -struct sdram_timing *__ddr_scan_option(struct sdram_timing *default_val) -{ - return default_val; -} -struct sdram_timing *ddr_scan_option(struct sdram_timing *) - __attribute__((weak, alias("__ddr_scan_option"))); - -u32 __ddr_rdss_opt(u32 default_val) -{ - return default_val; -} -u32 ddr_rdss_opt(ulong) __attribute__((weak, alias("__ddr_rdss_opt"))); - - -static u32 *get_membase(int bxcr_num) -{ - ulong bxcf; - u32 *membase; - -#if defined(SDRAM_R0BAS) - /* BAS from Memory Queue rank reg. */ - membase = - (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num))); - bxcf = 0; /* just to satisfy the compiler */ -#else - /* BAS from SDRAM_MBxCF mem rank reg. */ - mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); - membase = (u32 *)((bxcf & 0xfff80000) << 3); -#endif - - return membase; -} - -static inline void ecc_clear_status_reg(void) -{ - mtsdram(SDRAM_ECCES, 0xffffffff); -#if defined(SDRAM_R0BAS) - mtdcr(SDRAM_ERRSTATLL, 0xffffffff); -#endif -} - -/* - * Reset and relock memory DLL after SDRAM_CLKTR change - */ -static inline void relock_memory_DLL(void) -{ - u32 reg; - - mtsdram(SDRAM_MCOPT2, SDRAM_MCOPT2_IPTR_EXECUTE); - - do { - mfsdram(SDRAM_MCSTAT, reg); - } while (!(reg & SDRAM_MCSTAT_MIC_COMP)); - - mfsdram(SDRAM_MCOPT2, reg); - mtsdram(SDRAM_MCOPT2, reg | SDRAM_MCOPT2_DCEN_ENABLE); -} - -static int ecc_check_status_reg(void) -{ - u32 ecc_status; - - /* - * Compare suceeded, now check - * if got ecc error. If got an - * ecc error, then don't count - * this as a passing value - */ - mfsdram(SDRAM_ECCES, ecc_status); - if (ecc_status != 0x00000000) { - /* clear on error */ - ecc_clear_status_reg(); - /* ecc check failure */ - return 0; - } - ecc_clear_status_reg(); - sync(); - - return 1; -} - -/* return 1 if passes, 0 if fail */ -static int short_mem_test(u32 *base_address) -{ - int i, j, l; - u32 ecc_mode = 0; - - ulong test[NUMMEMTESTS][NUMMEMWORDS] = { - /* 0 */ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, - /* 1 */ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}, - /* 2 */ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555}, - /* 3 */ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA}, - /* 4 */ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A}, - /* 5 */ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5}, - /* 6 */ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA}, - /* 7 */ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55}, - -#if defined(CONFIG_SYS_DECREMENT_PATTERNS) - /* 8 */ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, - /* 9 */ {0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe, - 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe, - 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe, - 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe}, - /* 10 */{0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd, - 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd, - 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd, - 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd}, - /* 11 */{0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, - 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, - 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, - 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc}, - /* 12 */{0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb, - 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb, - 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb, - 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb}, - /* 13 */{0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa, - 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa, - 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa, - 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa}, - /* 14 */{0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, - 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, - 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, - 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9}, - /* 15 */{0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, - 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, - 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, - 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8}, - /* 16 */{0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7, - 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7, - 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7, - 0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7}, - /* 17 */{0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7, - 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7, - 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7, - 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7}, - /* 18 */{0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5, - 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5, - 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5, - 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5}, - /* 19 */{0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4, - 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4, - 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4, - 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4}, - /* 20 */{0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3, - 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3, - 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3, - 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3}, - /* 21 */{0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2, - 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2, - 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2, - 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2}, - /* 22 */{0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1, - 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1, - 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1, - 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1}, - /* 23 */{0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, - 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, - 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, - 0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0}, -#endif /* CONFIG_SYS_DECREMENT_PATTERNS */ - }; - - mfsdram(SDRAM_MCOPT1, ecc_mode); - if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) == - SDRAM_MCOPT1_MCHK_CHK_REP) { - ecc_clear_status_reg(); - sync(); - ecc_mode = 1; - } else { - ecc_mode = 0; - } - - /* - * Run the short memory test. - */ - for (i = 0; i < NUMMEMTESTS; i++) { - for (j = 0; j < NUMMEMWORDS; j++) { - base_address[j] = test[i][j]; - ppcDcbf((ulong)&(base_address[j])); - } - sync(); - iobarrier_rw(); - for (l = 0; l < NUMLOOPS; l++) { - for (j = 0; j < NUMMEMWORDS; j++) { - if (base_address[j] != test[i][j]) { - ppcDcbf((u32)&(base_address[j])); - return 0; - } else { - if (ecc_mode) { - if (!ecc_check_status_reg()) - return 0; - } - } - ppcDcbf((u32)&(base_address[j])); - } /* for (j = 0; j < NUMMEMWORDS; j++) */ - sync(); - iobarrier_rw(); - } /* for (l=0; l<NUMLOOPS; l++) */ - } - - return 1; -} - -#if defined(CONFIG_PPC4xx_DDR_METHOD_A) -/*-----------------------------------------------------------------------------+ -| program_DQS_calibration_methodA. -+-----------------------------------------------------------------------------*/ -static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal) -{ - u32 pass_result = 0; - -#ifdef DEBUG - ulong temp; - - mfsdram(SDRAM_RDCC, temp); - debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp); -#endif - - pass_result = DQS_calibration_methodA(ddrcal); - - return pass_result; -} - -/* - * DQS_calibration_methodA() - * - * Autocalibration Method A - * - * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros - * ARRAY [Entire FDBK Range] FDBK_Valid_Window; initialized to all zeros - * MEMWRITE(addr, expected_data); - * for (i = 0; i < Entire DQS Range; i++) { RQDC.RQFD - * for (j = 0; j < Entire FDBK Range; j++) { RFDC.RFFD - * MEMREAD(addr, actual_data); - * if (actual_data == expected_data) { - * DQS_Valid_Window[i] = 1; RQDC.RQFD - * FDBK_Valid_Window[i][j] = 1; RFDC.RFFD - * } - * } - * } - */ -static u32 DQS_calibration_methodA(struct ddrautocal *cal) -{ - ulong rfdc_reg; - ulong rffd; - - ulong rqdc_reg; - ulong rqfd; - - u32 *membase; - ulong bxcf; - int rqfd_average; - int bxcr_num; - int rffd_average; - int pass; - u32 passed = 0; - - int in_window; - struct autocal_regs curr_win_min; - struct autocal_regs curr_win_max; - struct autocal_regs best_win_min; - struct autocal_regs best_win_max; - struct autocal_regs loop_win_min; - struct autocal_regs loop_win_max; - -#ifdef DEBUG - ulong temp; -#endif - ulong rdcc; - - char slash[] = "\\|/-\\|/-"; - int loopi = 0; - - /* start */ - in_window = 0; - - memset(&curr_win_min, 0, sizeof(curr_win_min)); - memset(&curr_win_max, 0, sizeof(curr_win_max)); - memset(&best_win_min, 0, sizeof(best_win_min)); - memset(&best_win_max, 0, sizeof(best_win_max)); - memset(&loop_win_min, 0, sizeof(loop_win_min)); - memset(&loop_win_max, 0, sizeof(loop_win_max)); - - rdcc = 0; - - /* - * Program RDCC register - * Read sample cycle auto-update enable - */ - mtsdram(SDRAM_RDCC, - ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE); - -#ifdef DEBUG - mfsdram(SDRAM_RDCC, temp); - debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp); - mfsdram(SDRAM_RTSR, temp); - debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp); - mfsdram(SDRAM_FCSR, temp); - debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp); -#endif - - /* - * Program RQDC register - * Internal DQS delay mechanism enable - */ - mtsdram(SDRAM_RQDC, - SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00)); - -#ifdef DEBUG - mfsdram(SDRAM_RQDC, temp); - debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp); -#endif - - /* - * Program RFDC register - * Set Feedback Fractional Oversample - * Auto-detect read sample cycle enable - */ - mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE | - SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0)); - -#ifdef DEBUG - mfsdram(SDRAM_RFDC, temp); - debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp); -#endif - - putc(' '); - for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) { - - mfsdram(SDRAM_RQDC, rqdc_reg); - rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); - mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd)); - - putc('\b'); - putc(slash[loopi++ % 8]); - - curr_win_min.rffd = 0; - curr_win_max.rffd = 0; - in_window = 0; - - for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) { - mfsdram(SDRAM_RFDC, rfdc_reg); - rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); - mtsdram(SDRAM_RFDC, - rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd)); - - for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { - mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); - - /* Banks enabled */ - if (bxcf & SDRAM_BXCF_M_BE_MASK) { - /* Bank is enabled */ - membase = get_membase(bxcr_num); - pass = short_mem_test(membase); - } /* if bank enabled */ - } /* for bxcr_num */ - - /* If this value passed update RFFD windows */ - if (pass && !in_window) { /* at the start of window */ - in_window = 1; - curr_win_min.rffd = curr_win_max.rffd = rffd; - curr_win_min.rqfd = curr_win_max.rqfd = rqfd; - mfsdram(SDRAM_RDCC, rdcc); /*record this value*/ - } else if (!pass && in_window) { /* at end of window */ - in_window = 0; - } else if (pass && in_window) { /* within the window */ - curr_win_max.rffd = rffd; - curr_win_max.rqfd = rqfd; - } - /* else if (!pass && !in_window) - skip - no pass, not currently in a window */ - - if (in_window) { - if ((curr_win_max.rffd - curr_win_min.rffd) > - (best_win_max.rffd - best_win_min.rffd)) { - best_win_min.rffd = curr_win_min.rffd; - best_win_max.rffd = curr_win_max.rffd; - - best_win_min.rqfd = curr_win_min.rqfd; - best_win_max.rqfd = curr_win_max.rqfd; - cal->rdcc = rdcc; - } - passed = 1; - } - } /* RFDC.RFFD */ - - /* - * save-off the best window results of the RFDC.RFFD - * for this RQDC.RQFD setting - */ - /* - * if (just ended RFDC.RFDC loop pass window) > - * (prior RFDC.RFFD loop pass window) - */ - if ((best_win_max.rffd - best_win_min.rffd) > - (loop_win_max.rffd - loop_win_min.rffd)) { - loop_win_min.rffd = best_win_min.rffd; - loop_win_max.rffd = best_win_max.rffd; - loop_win_min.rqfd = rqfd; - loop_win_max.rqfd = rqfd; - debug("RQFD.min 0x%08x, RQFD.max 0x%08x, " - "RFFD.min 0x%08x, RFFD.max 0x%08x\n", - loop_win_min.rqfd, loop_win_max.rqfd, - loop_win_min.rffd, loop_win_max.rffd); - } - } /* RQDC.RQFD */ - - putc('\b'); - - debug("\n"); - - if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) && - (best_win_min.rffd == 0) && (best_win_max.rffd == 0) && - (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) { - passed = 0; - } - - /* - * Need to program RQDC before RFDC. - */ - debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd); - debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd); - rqfd_average = loop_win_max.rqfd; - - if (rqfd_average < 0) - rqfd_average = 0; - - if (rqfd_average > SDRAM_RQDC_RQFD_MAX) - rqfd_average = SDRAM_RQDC_RQFD_MAX; - - debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average); - mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | - SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); - - debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd); - debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd); - rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2); - - if (rffd_average < 0) - rffd_average = 0; - - if (rffd_average > SDRAM_RFDC_RFFD_MAX) - rffd_average = SDRAM_RFDC_RFFD_MAX; - - debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average); - mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average)); - - /* if something passed, then return the size of the largest window */ - if (passed != 0) { - passed = loop_win_max.rffd - loop_win_min.rffd; - cal->rqfd = rqfd_average; - cal->rffd = rffd_average; - cal->rffd_min = loop_win_min.rffd; - cal->rffd_max = loop_win_max.rffd; - } - - return (u32)passed; -} - -#else /* !defined(CONFIG_PPC4xx_DDR_METHOD_A) */ - -/*-----------------------------------------------------------------------------+ -| program_DQS_calibration_methodB. -+-----------------------------------------------------------------------------*/ -static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal) -{ - u32 pass_result = 0; - -#ifdef DEBUG - ulong temp; -#endif - - /* - * Program RDCC register - * Read sample cycle auto-update enable - */ - mtsdram(SDRAM_RDCC, - ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE); - -#ifdef DEBUG - mfsdram(SDRAM_RDCC, temp); - debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp); -#endif - - /* - * Program RQDC register - * Internal DQS delay mechanism enable - */ - mtsdram(SDRAM_RQDC, -#if defined(CONFIG_DDR_RQDC_START_VAL) - SDRAM_RQDC_RQDE_ENABLE | - SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL)); -#else - SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38)); -#endif - -#ifdef DEBUG - mfsdram(SDRAM_RQDC, temp); - debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp); -#endif - - /* - * Program RFDC register - * Set Feedback Fractional Oversample - * Auto-detect read sample cycle enable - */ - mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE | - SDRAM_RFDC_RFOS_ENCODE(0) | - SDRAM_RFDC_RFFD_ENCODE(0)); - -#ifdef DEBUG - mfsdram(SDRAM_RFDC, temp); - debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp); -#endif - - pass_result = DQS_calibration_methodB(ddrcal); - - return pass_result; -} - -/* - * DQS_calibration_methodB() - * - * Autocalibration Method B - * - * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros - * ARRAY [Entire Feedback Range] FDBK_Valid_Window; initialized to all zeros - * MEMWRITE(addr, expected_data); - * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38). - * - * for (j = 0; j < Entire Feedback Range; j++) { - * MEMREAD(addr, actual_data); - * if (actual_data == expected_data) { - * FDBK_Valid_Window[j] = 1; - * } - * } - * - * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window. - * - * for (i = 0; i < Entire DQS Range; i++) { - * MEMREAD(addr, actual_data); - * if (actual_data == expected_data) { - * DQS_Valid_Window[i] = 1; - * } - * } - * - * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window. - */ -/*-----------------------------------------------------------------------------+ -| DQS_calibration_methodB. -+-----------------------------------------------------------------------------*/ -static u32 DQS_calibration_methodB(struct ddrautocal *cal) -{ - ulong rfdc_reg; - ulong rffd; - - ulong rqdc_reg; - ulong rqfd; - - ulong rdcc; - - u32 *membase; - ulong bxcf; - int rqfd_average; - int bxcr_num; - int rffd_average; - int pass; - uint passed = 0; - - int in_window; - u32 curr_win_min, curr_win_max; - u32 best_win_min, best_win_max; - u32 size = 0; - - /*------------------------------------------------------------------ - | Test to determine the best read clock delay tuning bits. - | - | Before the DDR controller can be used, the read clock delay needs to - | be set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD]. - | This value cannot be hardcoded into the program because it changes - | depending on the board's setup and environment. - | To do this, all delay values are tested to see if they - | work or not. By doing this, you get groups of fails with groups of - | passing values. The idea is to find the start and end of a passing - | window and take the center of it to use as the read clock delay. - | - | A failure has to be seen first so that when we hit a pass, we know - | that it is truely the start of the window. If we get passing values - | to start off with, we don't know if we are at the start of the window - | - | The code assumes that a failure will always be found. - | If a failure is not found, there is no easy way to get the middle - | of the passing window. I guess we can pretty much pick any value - | but some values will be better than others. Since the lowest speed - | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed), - | from experimentation it is safe to say you will always have a failure - +-----------------------------------------------------------------*/ - - debug("\n\n"); - -#if defined(CONFIG_DDR_RFDC_FIXED) - mtsdram(SDRAM_RFDC, CONFIG_DDR_RFDC_FIXED); - size = 512; - rffd_average = CONFIG_DDR_RFDC_FIXED & SDRAM_RFDC_RFFD_MASK; - mfsdram(SDRAM_RDCC, rdcc); /* record this value */ - cal->rdcc = rdcc; -#else /* CONFIG_DDR_RFDC_FIXED */ - in_window = 0; - rdcc = 0; - - curr_win_min = curr_win_max = 0; - best_win_min = best_win_max = 0; - for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) { - mfsdram(SDRAM_RFDC, rfdc_reg); - rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); - mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd)); - - pass = 1; - for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { - mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); - - /* Banks enabled */ - if (bxcf & SDRAM_BXCF_M_BE_MASK) { - /* Bank is enabled */ - membase = get_membase(bxcr_num); - pass &= short_mem_test(membase); - } /* if bank enabled */ - } /* for bxcf_num */ - - /* If this value passed */ - if (pass && !in_window) { /* start of passing window */ - in_window = 1; - curr_win_min = curr_win_max = rffd; - mfsdram(SDRAM_RDCC, rdcc); /* record this value */ - } else if (!pass && in_window) { /* end passing window */ - in_window = 0; - } else if (pass && in_window) { /* within the passing window */ - curr_win_max = rffd; - } - - if (in_window) { - if ((curr_win_max - curr_win_min) > - (best_win_max - best_win_min)) { - best_win_min = curr_win_min; - best_win_max = curr_win_max; - cal->rdcc = rdcc; - } - passed = 1; - } - } /* for rffd */ - - if ((best_win_min == 0) && (best_win_max == 0)) - passed = 0; - else - size = best_win_max - best_win_min; - - debug("RFFD Min: 0x%x\n", best_win_min); - debug("RFFD Max: 0x%x\n", best_win_max); - rffd_average = ((best_win_min + best_win_max) / 2); - - cal->rffd_min = best_win_min; - cal->rffd_max = best_win_max; - - if (rffd_average < 0) - rffd_average = 0; - - if (rffd_average > SDRAM_RFDC_RFFD_MAX) - rffd_average = SDRAM_RFDC_RFFD_MAX; - - mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average)); -#endif /* CONFIG_DDR_RFDC_FIXED */ - - rffd = rffd_average; - in_window = 0; - - curr_win_min = curr_win_max = 0; - best_win_min = best_win_max = 0; - for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) { - mfsdram(SDRAM_RQDC, rqdc_reg); - rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); - mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd)); - - pass = 1; - for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { - - mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); - - /* Banks enabled */ - if (bxcf & SDRAM_BXCF_M_BE_MASK) { - /* Bank is enabled */ - membase = get_membase(bxcr_num); - pass &= short_mem_test(membase); - } /* if bank enabled */ - } /* for bxcf_num */ - - /* If this value passed */ - if (pass && !in_window) { - in_window = 1; - curr_win_min = curr_win_max = rqfd; - } else if (!pass && in_window) { - in_window = 0; - } else if (pass && in_window) { - curr_win_max = rqfd; - } - - if (in_window) { - if ((curr_win_max - curr_win_min) > - (best_win_max - best_win_min)) { - best_win_min = curr_win_min; - best_win_max = curr_win_max; - } - passed = 1; - } - } /* for rqfd */ - - if ((best_win_min == 0) && (best_win_max == 0)) - passed = 0; - - debug("RQFD Min: 0x%x\n", best_win_min); - debug("RQFD Max: 0x%x\n", best_win_max); - rqfd_average = ((best_win_min + best_win_max) / 2); - - if (rqfd_average < 0) - rqfd_average = 0; - - if (rqfd_average > SDRAM_RQDC_RQFD_MAX) - rqfd_average = SDRAM_RQDC_RQFD_MAX; - - mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | - SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); - - mfsdram(SDRAM_RQDC, rqdc_reg); - mfsdram(SDRAM_RFDC, rfdc_reg); - - /* - * Need to program RQDC before RFDC. The value is read above. - * That is the reason why auto cal not work. - * See, comments below. - */ - mtsdram(SDRAM_RQDC, rqdc_reg); - mtsdram(SDRAM_RFDC, rfdc_reg); - - debug("RQDC: 0x%08X\n", rqdc_reg); - debug("RFDC: 0x%08X\n", rfdc_reg); - - /* if something passed, then return the size of the largest window */ - if (passed != 0) { - passed = size; - cal->rqfd = rqfd_average; - cal->rffd = rffd_average; - } - - return (uint)passed; -} -#endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) */ - -/* - * Default table for DDR auto-calibration of all - * possible WRDTR and CLKTR values. - * Table format is: - * {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} - * - * Table is terminated with {-1, -1} value pair. - * - * Board vendors can specify their own board specific subset of - * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value - * pairs via a board defined ddr_scan_option() function. - */ -static struct sdram_timing full_scan_options[] = { - {0, 0}, {0, 1}, {0, 2}, {0, 3}, - {1, 0}, {1, 1}, {1, 2}, {1, 3}, - {2, 0}, {2, 1}, {2, 2}, {2, 3}, - {3, 0}, {3, 1}, {3, 2}, {3, 3}, - {4, 0}, {4, 1}, {4, 2}, {4, 3}, - {5, 0}, {5, 1}, {5, 2}, {5, 3}, - {6, 0}, {6, 1}, {6, 2}, {6, 3}, - {-1, -1} -}; - -/*---------------------------------------------------------------------------+ -| DQS_calibration. -+----------------------------------------------------------------------------*/ -u32 DQS_autocalibration(void) -{ - u32 wdtr; - u32 clkp; - u32 result = 0; - u32 best_result = 0; - u32 best_rdcc; - struct ddrautocal ddrcal; - struct autocal_clks tcal; - ulong rfdc_reg; - ulong rqdc_reg; - u32 val; - int verbose_lvl = 0; - char *str; - char slash[] = "\\|/-\\|/-"; - int loopi = 0; - struct sdram_timing *scan_list; - -#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION) - int i; - char tmp[64]; /* long enough for environment variables */ -#endif - - memset(&tcal, 0, sizeof(tcal)); - - scan_list = ddr_scan_option(full_scan_options); - - mfsdram(SDRAM_MCOPT1, val); - if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP) - str = "ECC Auto calibration -"; - else - str = "Auto calibration -"; - - puts(str); - -#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION) - i = getenv_f("autocalib", tmp, sizeof(tmp)); - if (i < 0) - strcpy(tmp, CONFIG_AUTOCALIB); - - if (strcmp(tmp, "final") == 0) { - /* display the final autocalibration results only */ - verbose_lvl = 1; - } else if (strcmp(tmp, "loop") == 0) { - /* display summary autocalibration info per iteration */ - verbose_lvl = 2; - } else if (strcmp(tmp, "display") == 0) { - /* display full debug autocalibration window info. */ - verbose_lvl = 3; - } -#endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */ - - best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30); - - while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) { - wdtr = scan_list->wrdtr; - clkp = scan_list->clktr; - - mfsdram(SDRAM_WRDTR, val); - val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK); - mtsdram(SDRAM_WRDTR, (val | - ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25)))); - - mtsdram(SDRAM_CLKTR, clkp << 30); - - relock_memory_DLL(); - - putc('\b'); - putc(slash[loopi++ % 8]); - -#ifdef DEBUG - debug("\n"); - debug("*** --------------\n"); - mfsdram(SDRAM_WRDTR, val); - debug("*** SDRAM_WRDTR set to 0x%08x\n", val); - mfsdram(SDRAM_CLKTR, val); - debug("*** SDRAM_CLKTR set to 0x%08x\n", val); -#endif - - debug("\n"); - if (verbose_lvl > 2) { - printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr); - printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp); - } - - memset(&ddrcal, 0, sizeof(ddrcal)); - - /* - * DQS calibration. - */ - /* - * program_DQS_calibration_method[A|B]() returns 0 if no - * passing RFDC.[RFFD] window is found or returns the size - * of the best passing window; in the case of a found passing - * window, the ddrcal will contain the values of the best - * window RQDC.[RQFD] and RFDC.[RFFD]. - */ - - /* - * Call PPC4xx SDRAM DDR autocalibration methodA or methodB. - * Default is methodB. - * Defined the autocalibration method in the board specific - * header file. - * Please see include/configs/kilauea.h for an example for - * a board specific implementation. - */ -#if defined(CONFIG_PPC4xx_DDR_METHOD_A) - result = program_DQS_calibration_methodA(&ddrcal); -#else - result = program_DQS_calibration_methodB(&ddrcal); -#endif - - sync(); - - /* - * Clear potential errors resulting from auto-calibration. - * If not done, then we could get an interrupt later on when - * exceptions are enabled. - */ - set_mcsr(get_mcsr()); - - val = ddrcal.rdcc; /* RDCC from the best passing window */ - - udelay(100); - - if (verbose_lvl > 1) { - char *tstr; - switch ((val >> 30)) { - case 0: - if (result != 0) - tstr = "T1"; - else - tstr = "N/A"; - break; - case 1: - tstr = "T2"; - break; - case 2: - tstr = "T3"; - break; - case 3: - tstr = "T4"; - break; - default: - tstr = "unknown"; - break; - } - printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), " - "max-min(0x%04x)(0x%04x), RDCC: %s\n", - wdtr, clkp, result, best_result, - ddrcal.rffd_min, ddrcal.rffd_max, tstr); - } - - /* - * The DQS calibration "result" is either "0" - * if no passing window was found, or is the - * size of the RFFD passing window. - */ - /* - * want the lowest Read Sample Cycle Select - */ - val = SDRAM_RDCC_RDSS_DECODE(val); - debug("*** (%d) (%d) current_rdcc, best_rdcc\n", - val, best_rdcc); - - if ((result != 0) && - (val >= SDRAM_RDCC_RDSS_VAL(SDRAM_RDCC_RDSS_T2))) { - if (((result == best_result) && (val < best_rdcc)) || - ((result > best_result) && (val <= best_rdcc))) { - tcal.autocal.flags = 1; - debug("*** (%d)(%d) result passed window " - "size: 0x%08x, rqfd = 0x%08x, " - "rffd = 0x%08x, rdcc = 0x%08x\n", - wdtr, clkp, result, ddrcal.rqfd, - ddrcal.rffd, ddrcal.rdcc); - - /* - * Save the SDRAM_WRDTR and SDRAM_CLKTR - * settings for the largest returned - * RFFD passing window size. - */ - best_rdcc = val; - tcal.clocks.wrdtr = wdtr; - tcal.clocks.clktr = clkp; - tcal.clocks.rdcc = SDRAM_RDCC_RDSS_ENCODE(val); - tcal.autocal.rqfd = ddrcal.rqfd; - tcal.autocal.rffd = ddrcal.rffd; - best_result = result; - - if (verbose_lvl > 2) { - printf("** (%d)(%d) " - "best result: 0x%04x\n", - wdtr, clkp, - best_result); - printf("** (%d)(%d) " - "best WRDTR: 0x%04x\n", - wdtr, clkp, - tcal.clocks.wrdtr); - printf("** (%d)(%d) " - "best CLKTR: 0x%04x\n", - wdtr, clkp, - tcal.clocks.clktr); - printf("** (%d)(%d) " - "best RQDC: 0x%04x\n", - wdtr, clkp, - tcal.autocal.rqfd); - printf("** (%d)(%d) " - "best RFDC: 0x%04x\n", - wdtr, clkp, - tcal.autocal.rffd); - printf("** (%d)(%d) " - "best RDCC: 0x%08x\n", - wdtr, clkp, - (u32)tcal.clocks.rdcc); - mfsdram(SDRAM_RTSR, val); - printf("** (%d)(%d) best " - "loop RTSR: 0x%08x\n", - wdtr, clkp, val); - mfsdram(SDRAM_FCSR, val); - printf("** (%d)(%d) best " - "loop FCSR: 0x%08x\n", - wdtr, clkp, val); - } - } - } /* if ((result != 0) && (val >= (ddr_rdss_opt()))) */ - scan_list++; - } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */ - - if (tcal.autocal.flags == 1) { - if (verbose_lvl > 0) { - printf("*** --------------\n"); - printf("*** best_result window size: %d\n", - best_result); - printf("*** best_result WRDTR: 0x%04x\n", - tcal.clocks.wrdtr); - printf("*** best_result CLKTR: 0x%04x\n", - tcal.clocks.clktr); - printf("*** best_result RQFD: 0x%04x\n", - tcal.autocal.rqfd); - printf("*** best_result RFFD: 0x%04x\n", - tcal.autocal.rffd); - printf("*** best_result RDCC: 0x%04x\n", - tcal.clocks.rdcc); - printf("*** --------------\n"); - printf("\n"); - } - - /* - * if got best passing result window, then lock in the - * best CLKTR, WRDTR, RQFD, and RFFD values - */ - mfsdram(SDRAM_WRDTR, val); - mtsdram(SDRAM_WRDTR, (val & - ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) | - ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | - (tcal.clocks.wrdtr << 25))); - - mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30); - - relock_memory_DLL(); - - mfsdram(SDRAM_RQDC, rqdc_reg); - rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); - mtsdram(SDRAM_RQDC, rqdc_reg | - SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd)); - - mfsdram(SDRAM_RQDC, rqdc_reg); - debug("*** best_result: read value SDRAM_RQDC 0x%08x\n", - rqdc_reg); - -#if defined(CONFIG_DDR_RFDC_FIXED) - mtsdram(SDRAM_RFDC, CONFIG_DDR_RFDC_FIXED); -#else /* CONFIG_DDR_RFDC_FIXED */ - mfsdram(SDRAM_RFDC, rfdc_reg); - rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); - mtsdram(SDRAM_RFDC, rfdc_reg | - SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd)); -#endif /* CONFIG_DDR_RFDC_FIXED */ - - mfsdram(SDRAM_RFDC, rfdc_reg); - debug("*** best_result: read value SDRAM_RFDC 0x%08x\n", - rfdc_reg); - mfsdram(SDRAM_RDCC, val); - debug("*** SDRAM_RDCC 0x%08x\n", val); - } else { - /* - * no valid windows were found - */ - printf("DQS memory calibration window can not be determined, " - "terminating u-boot.\n"); - ppc4xx_ibm_ddr2_register_dump(); - spd_ddr_init_hang(); - } - - blank_string(strlen(str)); - - return 0; -} -#else /* defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */ -u32 DQS_autocalibration(void) -{ - return 0; -} -#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */ diff --git a/arch/powerpc/cpu/ppc4xx/4xx_pci.c b/arch/powerpc/cpu/ppc4xx/4xx_pci.c deleted file mode 100644 index 80b0c1c..0000000 --- a/arch/powerpc/cpu/ppc4xx/4xx_pci.c +++ /dev/null @@ -1,883 +0,0 @@ -/*-----------------------------------------------------------------------------+ - * 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 - *-----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------+ - * - * File Name: 405gp_pci.c - * - * Function: Initialization code for the 405GP PCI Configuration regs. - * - * Author: Mark Game - * - * Change Activity- - * - * Date Description of Change BY - * --------- --------------------- --- - * 09-Sep-98 Created MCG - * 02-Nov-98 Removed External arbiter selected message JWB - * 27-Nov-98 Zero out PTMBAR2 and disable in PTM2MS JWB - * 04-Jan-99 Zero out other unused PMM and PTM regs. Change bus scan MCG - * from (0 to n) to (1 to n). - * 17-May-99 Port to Walnut JWB - * 17-Jun-99 Updated for VGA support JWB - * 21-Jun-99 Updated to allow SRAM region to be a target from PCI bus JWB - * 19-Jul-99 Updated for 405GP pass 1 errata #26 (Low PCI subsequent MCG - * target latency timer values are not supported). - * Should be fixed in pass 2. - * 09-Sep-99 Removed use of PTM2 since the SRAM region no longer needs JWB - * to be a PCI target. Zero out PTMBAR2 and disable in PTM2MS. - * 10-Dec-99 Updated PCI_Write_CFG_Reg for pass2 errata #6 JWB - * 11-Jan-00 Ensure PMMxMAs disabled before setting PMMxLAs. This is not - * really required after a reset since PMMxMAs are already - * disabled but is a good practice nonetheless. JWB - * 12-Jun-01 stefan.roese@esd-electronics.com - * - PCI host/adapter handling reworked - * 09-Jul-01 stefan.roese@esd-electronics.com - * - PCI host now configures from device 0 (not 1) to max_dev, - * (host configures itself) - * - On CPCI-405 pci base address and size is generated from - * SDRAM and FLASH size (CFG regs not used anymore) - * - Some minor changes for CPCI-405-A (adapter version) - * 14-Sep-01 stefan.roese@esd-electronics.com - * - CONFIG_PCI_SCAN_SHOW added to print pci devices upon startup - * 28-Sep-01 stefan.roese@esd-electronics.com - * - Changed pci master configuration for linux compatibility - * (no need for bios_fixup() anymore) - * 26-Feb-02 stefan.roese@esd-electronics.com - * - Bug fixed in pci configuration (Andrew May) - * - Removed pci class code init for CPCI405 board - * 15-May-02 stefan.roese@esd-electronics.com - * - New vga device handling - * 29-May-02 stefan.roese@esd-electronics.com - * - PCI class code init added (if defined) - *----------------------------------------------------------------------------*/ - -#include <common.h> -#include <command.h> -#include <asm/4xx_pci.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <pci.h> - -#ifdef CONFIG_PCI - -DECLARE_GLOBAL_DATA_PTR; - -#if defined(CONFIG_405GP) || defined(CONFIG_405EP) - -#if defined(CONFIG_PMC405) -ushort pmc405_pci_subsys_deviceid(void); -#endif - -/*#define DEBUG*/ - -/* - * Board-specific pci initialization - * Platform code can reimplement pci_pre_init() if needed - */ -int __pci_pre_init(struct pci_controller *hose) -{ -#if defined(CONFIG_405EP) - /* - * Enable the internal PCI arbiter by default. - * - * On 405EP CPUs the internal arbiter can be controlled - * by the I2C strapping EEPROM. If you want to do so - * or if you want to disable the arbiter pci_pre_init() - * must be reimplemented without enabling the arbiter. - * The arbiter is enabled in this place because of - * compatibility reasons. - */ - mtdcr(CPC0_PCI, mfdcr(CPC0_PCI) | CPC0_PCI_ARBIT_EN); -#endif /* CONFIG_405EP */ - - return 1; -} -int pci_pre_init(struct pci_controller *hose) - __attribute__((weak, alias("__pci_pre_init"))); - -int __is_pci_host(struct pci_controller *hose) -{ -#if defined(CONFIG_405GP) - if (mfdcr(CPC0_PSR) & PSR_PCI_ARBIT_EN) - return 1; -#elif defined (CONFIG_405EP) - if (mfdcr(CPC0_PCI) & CPC0_PCI_ARBIT_EN) - return 1; -#endif - return 0; -} -int is_pci_host(struct pci_controller *hose) __attribute__((weak, alias("__is_pci_host"))); - -/*-----------------------------------------------------------------------------+ - * pci_init. Initializes the 405GP PCI Configuration regs. - *-----------------------------------------------------------------------------*/ -void pci_405gp_init(struct pci_controller *hose) -{ - int i, reg_num = 0; - bd_t *bd = gd->bd; - - unsigned short temp_short; - unsigned long ptmpcila[2] = {CONFIG_SYS_PCI_PTM1PCI, CONFIG_SYS_PCI_PTM2PCI}; -#if defined(CONFIG_PCI_4xx_PTM_OVERWRITE) - char *ptmla_str, *ptmms_str; -#endif - unsigned long ptmla[2] = {CONFIG_SYS_PCI_PTM1LA, CONFIG_SYS_PCI_PTM2LA}; - unsigned long ptmms[2] = {CONFIG_SYS_PCI_PTM1MS, CONFIG_SYS_PCI_PTM2MS}; -#if defined(CONFIG_PIP405) || defined (CONFIG_MIP405) - unsigned long pmmla[3] = {0x80000000, 0xA0000000, 0}; - unsigned long pmmma[3] = {0xE0000001, 0xE0000001, 0}; - unsigned long pmmpcila[3] = {0x80000000, 0x00000000, 0}; - unsigned long pmmpciha[3] = {0x00000000, 0x00000000, 0}; -#else - unsigned long pmmla[3] = {0x80000000, 0,0}; - unsigned long pmmma[3] = {0xC0000001, 0,0}; - unsigned long pmmpcila[3] = {0x80000000, 0,0}; - unsigned long pmmpciha[3] = {0x00000000, 0,0}; -#endif -#ifdef CONFIG_PCI_PNP -#if (CONFIG_PCI_HOST == PCI_HOST_AUTO) - char *s; -#endif -#endif - -#if defined(CONFIG_PCI_4xx_PTM_OVERWRITE) - ptmla_str = getenv("ptm1la"); - ptmms_str = getenv("ptm1ms"); - if(NULL != ptmla_str && NULL != ptmms_str ) { - ptmla[0] = simple_strtoul (ptmla_str, NULL, 16); - ptmms[0] = simple_strtoul (ptmms_str, NULL, 16); - } - - ptmla_str = getenv("ptm2la"); - ptmms_str = getenv("ptm2ms"); - if(NULL != ptmla_str && NULL != ptmms_str ) { - ptmla[1] = simple_strtoul (ptmla_str, NULL, 16); - ptmms[1] = simple_strtoul (ptmms_str, NULL, 16); - } -#endif - - /* - * Register the hose - */ - hose->first_busno = 0; - hose->last_busno = 0xff; - - /* ISA/PCI I/O space */ - pci_set_region(hose->regions + reg_num++, - MIN_PCI_PCI_IOADDR, - MIN_PLB_PCI_IOADDR, - 0x10000, - PCI_REGION_IO); - - /* PCI I/O space */ - pci_set_region(hose->regions + reg_num++, - 0x00800000, - 0xe8800000, - 0x03800000, - PCI_REGION_IO); - - reg_num = 2; - - /* Memory spaces */ - for (i=0; i<2; i++) - if (ptmms[i] & 1) - { - if (!i) hose->pci_fb = hose->regions + reg_num; - - pci_set_region(hose->regions + reg_num++, - ptmpcila[i], ptmla[i], - ~(ptmms[i] & 0xfffff000) + 1, - PCI_REGION_MEM | - PCI_REGION_SYS_MEMORY); - } - - /* PCI memory spaces */ - for (i=0; i<3; i++) - if (pmmma[i] & 1) - { - pci_set_region(hose->regions + reg_num++, - pmmpcila[i], pmmla[i], - ~(pmmma[i] & 0xfffff000) + 1, - PCI_REGION_MEM); - } - - hose->region_count = reg_num; - - pci_setup_indirect(hose, - PCICFGADR, - PCICFGDATA); - - if (hose->pci_fb) - pciauto_region_init(hose->pci_fb); - - /* Let board change/modify hose & do initial checks */ - if (pci_pre_init(hose) == 0) { - printf("PCI: Board-specific initialization failed.\n"); - printf("PCI: Configuration aborted.\n"); - return; - } - - pci_register_hose(hose); - - /*--------------------------------------------------------------------------+ - * 405GP PCI Master configuration. - * Map one 512 MB range of PLB/processor addresses to PCI memory space. - * PLB address 0x80000000-0xBFFFFFFF ==> PCI address 0x80000000-0xBFFFFFFF - * Use byte reversed out routines to handle endianess. - *--------------------------------------------------------------------------*/ - out32r(PMM0MA, (pmmma[0]&~0x1)); /* disable, configure PMMxLA, PMMxPCILA first */ - out32r(PMM0LA, pmmla[0]); - out32r(PMM0PCILA, pmmpcila[0]); - out32r(PMM0PCIHA, pmmpciha[0]); - out32r(PMM0MA, pmmma[0]); - - /*--------------------------------------------------------------------------+ - * PMM1 is not used. Initialize them to zero. - *--------------------------------------------------------------------------*/ - out32r(PMM1MA, (pmmma[1]&~0x1)); - out32r(PMM1LA, pmmla[1]); - out32r(PMM1PCILA, pmmpcila[1]); - out32r(PMM1PCIHA, pmmpciha[1]); - out32r(PMM1MA, pmmma[1]); - - /*--------------------------------------------------------------------------+ - * PMM2 is not used. Initialize them to zero. - *--------------------------------------------------------------------------*/ - out32r(PMM2MA, (pmmma[2]&~0x1)); - out32r(PMM2LA, pmmla[2]); - out32r(PMM2PCILA, pmmpcila[2]); - out32r(PMM2PCIHA, pmmpciha[2]); - out32r(PMM2MA, pmmma[2]); - - /*--------------------------------------------------------------------------+ - * 405GP PCI Target configuration. (PTM1) - * Note: PTM1MS is hardwire enabled but we set the enable bit anyway. - *--------------------------------------------------------------------------*/ - out32r(PTM1LA, ptmla[0]); /* insert address */ - out32r(PTM1MS, ptmms[0]); /* insert size, enable bit is 1 */ - pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_1, ptmpcila[0]); - - /*--------------------------------------------------------------------------+ - * 405GP PCI Target configuration. (PTM2) - *--------------------------------------------------------------------------*/ - out32r(PTM2LA, ptmla[1]); /* insert address */ - pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, ptmpcila[1]); - - if (ptmms[1] == 0) - { - out32r(PTM2MS, 0x00000001); /* set enable bit */ - pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, 0x00000000); - out32r(PTM2MS, 0x00000000); /* disable */ - } - else - { - out32r(PTM2MS, ptmms[1]); /* insert size, enable bit is 1 */ - } - - /* - * Insert Subsystem Vendor and Device ID - */ - pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_VENDOR_ID, CONFIG_SYS_PCI_SUBSYS_VENDORID); -#ifdef CONFIG_CPCI405 - if (is_pci_host(hose)) - pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID); - else - pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID2); -#else - pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID); -#endif - - /* - * Insert Class-code - */ -#ifdef CONFIG_SYS_PCI_CLASSCODE - pci_write_config_word(PCIDEVID_405GP, PCI_CLASS_SUB_CODE, CONFIG_SYS_PCI_CLASSCODE); -#endif /* CONFIG_SYS_PCI_CLASSCODE */ - - /*--------------------------------------------------------------------------+ - * If PCI speed = 66MHz, set 66MHz capable bit. - *--------------------------------------------------------------------------*/ - if (bd->bi_pci_busfreq >= 66000000) { - pci_read_config_word(PCIDEVID_405GP, PCI_STATUS, &temp_short); - pci_write_config_word(PCIDEVID_405GP,PCI_STATUS,(temp_short|PCI_STATUS_66MHZ)); - } - -#if (CONFIG_PCI_HOST != PCI_HOST_ADAPTER) -#if (CONFIG_PCI_HOST == PCI_HOST_AUTO) - if (is_pci_host(hose) || - (((s = getenv("pciscan")) != NULL) && (strcmp(s, "yes") == 0))) -#endif - { - /*--------------------------------------------------------------------------+ - * Write the 405GP PCI Configuration regs. - * Enable 405GP to be a master on the PCI bus (PMM). - * Enable 405GP to act as a PCI memory target (PTM). - *--------------------------------------------------------------------------*/ - pci_read_config_word(PCIDEVID_405GP, PCI_COMMAND, &temp_short); - pci_write_config_word(PCIDEVID_405GP, PCI_COMMAND, temp_short | - PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); - } -#endif - -#if defined(CONFIG_405EP) - /* - * on ppc405ep vendor/device id is not set - * The user manual says 0x1014 (IBM) / 0x0156 (405GP!) - * are the correct values. - */ - pci_write_config_word(PCIDEVID_405GP, PCI_VENDOR_ID, PCI_VENDOR_ID_IBM); - pci_write_config_word(PCIDEVID_405GP, - PCI_DEVICE_ID, PCI_DEVICE_ID_IBM_405GP); -#endif - - /* - * Set HCE bit (Host Configuration Enabled) - */ - pci_read_config_word(PCIDEVID_405GP, PCIBRDGOPT2, &temp_short); - pci_write_config_word(PCIDEVID_405GP, PCIBRDGOPT2, (temp_short | 0x0001)); - -#ifdef CONFIG_PCI_PNP - /*--------------------------------------------------------------------------+ - * Scan the PCI bus and configure devices found. - *--------------------------------------------------------------------------*/ -#if (CONFIG_PCI_HOST == PCI_HOST_AUTO) - if (is_pci_host(hose) || - (((s = getenv("pciscan")) != NULL) && (strcmp(s, "yes") == 0))) -#endif - { -#ifdef CONFIG_PCI_SCAN_SHOW - printf("PCI: Bus Dev VenId DevId Class Int\n"); -#endif - hose->last_busno = pci_hose_scan(hose); - } -#endif /* CONFIG_PCI_PNP */ - -} - -/* - * drivers/pci/pci.c skips every host bridge but the 405GP since it could - * be set as an Adapter. - * - * I (Andrew May) don't know what we should do here, but I don't want - * the auto setup of a PCI device disabling what is done pci_405gp_init - * as has happened before. - */ -void pci_405gp_setup_bridge(struct pci_controller *hose, pci_dev_t dev, - struct pci_config_table *entry) -{ -#ifdef DEBUG - printf("405gp_setup_bridge\n"); -#endif -} - -/* - * - */ - -void pci_405gp_fixup_irq(struct pci_controller *hose, pci_dev_t dev) -{ - unsigned char int_line = 0xff; - - /* - * Write pci interrupt line register (cpci405 specific) - */ - switch (PCI_DEV(dev) & 0x03) - { - case 0: - int_line = 27 + 2; - break; - case 1: - int_line = 27 + 3; - break; - case 2: - int_line = 27 + 0; - break; - case 3: - int_line = 27 + 1; - break; - } - - pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line); -} - -void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev, - struct pci_config_table *entry) -{ - unsigned int cmdstat = 0; - - pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_prefetch, hose->pci_io); - - /* always enable io space on vga boards */ - pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat); - cmdstat |= PCI_COMMAND_IO; - pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat); -} - -#if !(defined(CONFIG_PIP405) || defined (CONFIG_MIP405)) && !(defined (CONFIG_SC3)) - -/* - *As is these functs get called out of flash Not a horrible - *thing, but something to keep in mind. (no statics?) - */ -static struct pci_config_table pci_405gp_config_table[] = { -/*if VendID is 0 it terminates the table search (ie Walnut)*/ -#ifdef CONFIG_SYS_PCI_SUBSYS_VENDORID - {CONFIG_SYS_PCI_SUBSYS_VENDORID, PCI_ANY_ID, PCI_CLASS_BRIDGE_HOST, - PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_bridge}, -#endif - {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}, - - { } -}; - -static struct pci_controller hose = { - fixup_irq: pci_405gp_fixup_irq, - config_table: pci_405gp_config_table, -}; - -void pci_init_board(void) -{ - /*we want the ptrs to RAM not flash (ie don't use init list)*/ - hose.fixup_irq = pci_405gp_fixup_irq; - hose.config_table = pci_405gp_config_table; - pci_405gp_init(&hose); -} - -#endif - -#endif /* CONFIG_405GP */ - -/*-----------------------------------------------------------------------------+ - * CONFIG_440 - *-----------------------------------------------------------------------------*/ -#if defined(CONFIG_440) - -#if defined(CONFIG_SYS_PCI_MASTER_INIT) || defined(CONFIG_SYS_PCI_TARGET_INIT) -static struct pci_controller ppc440_hose = {0}; -#endif - -/* - * This routine is called to determine if a pci scan should be - * performed. With various hardware environments (especially cPCI and - * PPMC) it's insufficient to depend on the state of the arbiter enable - * bit in the strap register, or generic host/adapter assumptions. - * - * Rather than hard-code a bad assumption in the general 440 code, the - * 440 pci code requires the board to decide at runtime. - * - * Return 0 for adapter mode, non-zero for host (monarch) mode. - * - * Weak default implementation: "Normal" boards implement the PCI - * host functionality. This can be overridden for PCI adapter boards. - */ -int __is_pci_host(struct pci_controller *hose) -{ - return 1; -} -int is_pci_host(struct pci_controller *hose) - __attribute__((weak, alias("__is_pci_host"))); - -#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX) - -#if defined(CONFIG_SYS_PCI_TARGET_INIT) -/* - * pci_target_init - * - * The bootstrap configuration provides default settings for the pci - * inbound map (PIM). But the bootstrap config choices are limited and - * may not be sufficient for a given board. - */ -void __pci_target_init(struct pci_controller *hose) -{ - /* - * Set up Direct MMIO registers - */ - - /* - * PowerPC440 EP PCI Master configuration. - * Map one 1Gig range of PLB/processor addresses to PCI memory space. - * PLB address 0xA0000000-0xDFFFFFFF ==> PCI address 0xA0000000-0xDFFFFFFF - * Use byte reversed out routines to handle endianess. - * Make this region non-prefetchable. - */ - /* PMM0 Mask/Attribute - disabled b4 setting */ - out_le32((void *)PCIL0_PMM0MA, 0x00000000); - /* PMM0 Local Address */ - out_le32((void *)PCIL0_PMM0LA, CONFIG_SYS_PCI_MEMBASE); - /* PMM0 PCI Low Address */ - out_le32((void *)PCIL0_PMM0PCILA, CONFIG_SYS_PCI_MEMBASE); - /* PMM0 PCI High Address */ - out_le32((void *)PCIL0_PMM0PCIHA, 0x00000000); - /* 512M + No prefetching, and enable region */ - out_le32((void *)PCIL0_PMM0MA, 0xE0000001); - - /* PMM1 Mask/Attribute - disabled b4 setting */ - out_le32((void *)PCIL0_PMM1MA, 0x00000000); - /* PMM1 Local Address */ - out_le32((void *)PCIL0_PMM1LA, CONFIG_SYS_PCI_MEMBASE2); - /* PMM1 PCI Low Address */ - out_le32((void *)PCIL0_PMM1PCILA, CONFIG_SYS_PCI_MEMBASE2); - /* PMM1 PCI High Address */ - out_le32((void *)PCIL0_PMM1PCIHA, 0x00000000); - /* 512M + No prefetching, and enable region */ - out_le32((void *)PCIL0_PMM1MA, 0xE0000001); - - out_le32((void *)PCIL0_PTM1MS, 0x00000001); /* Memory Size/Attribute */ - out_le32((void *)PCIL0_PTM1LA, 0); /* Local Addr. Reg */ - out_le32((void *)PCIL0_PTM2MS, 0); /* Memory Size/Attribute */ - out_le32((void *)PCIL0_PTM2LA, 0); /* Local Addr. Reg */ - - /* - * Set up Configuration registers - */ - - /* Program the board's subsystem id/vendor id */ - pci_write_config_word(0, PCI_SUBSYSTEM_VENDOR_ID, - CONFIG_SYS_PCI_SUBSYS_VENDORID); - pci_write_config_word(0, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_ID); - - /* Configure command register as bus master */ - pci_write_config_word(0, PCI_COMMAND, PCI_COMMAND_MASTER); - - /* 240nS PCI clock */ - pci_write_config_word(0, PCI_LATENCY_TIMER, 1); - - /* No error reporting */ - pci_write_config_word(0, PCI_ERREN, 0); - - pci_write_config_dword(0, PCI_BRDGOPT2, 0x00000101); -} -#endif /* CONFIG_SYS_PCI_TARGET_INIT */ - -/* - * pci_pre_init - * - * This routine is called just prior to registering the hose and gives - * the board the opportunity to check things. Returning a value of zero - * indicates that things are bad & PCI initialization should be aborted. - * - * Different boards may wish to customize the pci controller structure - * (add regions, override default access routines, etc) or perform - * certain pre-initialization actions. - * - */ -int __pci_pre_init(struct pci_controller *hose) -{ - u32 reg; - - /* - * Set priority for all PLB3 devices to 0. - * Set PLB3 arbiter to fair mode. - */ - mfsdr(SDR0_AMP1, reg); - mtsdr(SDR0_AMP1, (reg & 0x000000FF) | 0x0000FF00); - reg = mfdcr(PLB3A0_ACR); - mtdcr(PLB3A0_ACR, reg | 0x80000000); - - /* - * Set priority for all PLB4 devices to 0. - */ - mfsdr(SDR0_AMP0, reg); - mtsdr(SDR0_AMP0, (reg & 0x000000FF) | 0x0000FF00); - reg = mfdcr(PLB4A0_ACR) | 0xa0000000; - mtdcr(PLB4A0_ACR, reg); - - /* - * Set Nebula PLB4 arbiter to fair mode. - */ - /* Segment0 */ - reg = (mfdcr(PLB4A0_ACR) & ~PLB4Ax_ACR_PPM_MASK) | PLB4Ax_ACR_PPM_FAIR; - reg = (reg & ~PLB4Ax_ACR_HBU_MASK) | PLB4Ax_ACR_HBU_ENABLED; - reg = (reg & ~PLB4Ax_ACR_RDP_MASK) | PLB4Ax_ACR_RDP_4DEEP; - reg = (reg & ~PLB4Ax_ACR_WRP_MASK) | PLB4Ax_ACR_WRP_2DEEP; - mtdcr(PLB4A0_ACR, reg); - - /* Segment1 */ - reg = (mfdcr(PLB4A1_ACR) & ~PLB4Ax_ACR_PPM_MASK) | PLB4Ax_ACR_PPM_FAIR; - reg = (reg & ~PLB4Ax_ACR_HBU_MASK) | PLB4Ax_ACR_HBU_ENABLED; - reg = (reg & ~PLB4Ax_ACR_RDP_MASK) | PLB4Ax_ACR_RDP_4DEEP; - reg = (reg & ~PLB4Ax_ACR_WRP_MASK) | PLB4Ax_ACR_WRP_2DEEP; - mtdcr(PLB4A1_ACR, reg); - -#if defined(CONFIG_SYS_PCI_BOARD_FIXUP_IRQ) - hose->fixup_irq = board_pci_fixup_irq; -#endif - - return 1; -} - -#else /* defined(CONFIG_440EP) ... */ - -#if defined(CONFIG_SYS_PCI_TARGET_INIT) -void __pci_target_init(struct pci_controller * hose) -{ - /* - * Disable everything - */ - out_le32((void *)PCIL0_PIM0SA, 0); /* disable */ - out_le32((void *)PCIL0_PIM1SA, 0); /* disable */ - out_le32((void *)PCIL0_PIM2SA, 0); /* disable */ - out_le32((void *)PCIL0_EROMBA, 0); /* disable expansion rom */ - - /* - * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440 - * strapping options do not support sizes such as 128/256 MB. - */ - out_le32((void *)PCIL0_PIM0LAL, CONFIG_SYS_SDRAM_BASE); - out_le32((void *)PCIL0_PIM0LAH, 0); - out_le32((void *)PCIL0_PIM0SA, ~(gd->ram_size - 1) | 1); - out_le32((void *)PCIL0_BAR0, 0); - - /* - * Program the board's subsystem id/vendor id - */ - out_le16((void *)PCIL0_SBSYSVID, CONFIG_SYS_PCI_SUBSYS_VENDORID); - out_le16((void *)PCIL0_SBSYSID, CONFIG_SYS_PCI_SUBSYS_DEVICEID); - - out_le16((void *)PCIL0_CMD, in_le16((void *)PCIL0_CMD) | - PCI_COMMAND_MEMORY); -} -#endif /* CONFIG_SYS_PCI_TARGET_INIT */ - -int __pci_pre_init(struct pci_controller *hose) -{ - /* - * This board is always configured as the host & requires the - * PCI arbiter to be enabled. - */ - if (!pci_arbiter_enabled()) { - printf("PCI: PCI Arbiter disabled!\n"); - return 0; - } - - return 1; -} - -#endif /* defined(CONFIG_440EP) ... */ - -#if defined(CONFIG_SYS_PCI_TARGET_INIT) -void pci_target_init(struct pci_controller * hose) - __attribute__((weak, alias("__pci_target_init"))); -#endif /* CONFIG_SYS_PCI_TARGET_INIT */ - -int pci_pre_init(struct pci_controller *hose) - __attribute__((weak, alias("__pci_pre_init"))); - -#if defined(CONFIG_SYS_PCI_MASTER_INIT) -void __pci_master_init(struct pci_controller *hose) -{ - u16 reg; - - /* - * Write the PowerPC440 EP PCI Configuration regs. - * Enable PowerPC440 EP to be a master on the PCI bus (PMM). - * Enable PowerPC440 EP to act as a PCI memory target (PTM). - */ - pci_read_config_word(0, PCI_COMMAND, ®); - pci_write_config_word(0, PCI_COMMAND, reg | - PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); -} -void pci_master_init(struct pci_controller *hose) - __attribute__((weak, alias("__pci_master_init"))); -#endif /* CONFIG_SYS_PCI_MASTER_INIT */ - -#if defined(CONFIG_SYS_PCI_MASTER_INIT) || defined(CONFIG_SYS_PCI_TARGET_INIT) -int pci_440_init (struct pci_controller *hose) -{ - int reg_num = 0; - -#ifndef CONFIG_DISABLE_PISE_TEST - /*--------------------------------------------------------------------------+ - * The PCI initialization sequence enable bit must be set ... if not abort - * pci setup since updating the bit requires chip reset. - *--------------------------------------------------------------------------*/ -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) - unsigned long strap; - - mfsdr(SDR0_SDSTP1,strap); - if ((strap & SDR0_SDSTP1_PISE_MASK) == 0) { - printf("PCI: SDR0_STRP1[PISE] not set.\n"); - printf("PCI: Configuration aborted.\n"); - return -1; - } -#elif defined(CONFIG_440GP) - unsigned long strap; - - strap = mfdcr(CPC0_STRP1); - if ((strap & CPC0_STRP1_PISE_MASK) == 0) { - printf("PCI: CPC0_STRP1[PISE] not set.\n"); - printf("PCI: Configuration aborted.\n"); - return -1; - } -#endif -#endif /* CONFIG_DISABLE_PISE_TEST */ - - /*--------------------------------------------------------------------------+ - * PCI controller init - *--------------------------------------------------------------------------*/ - hose->first_busno = 0; - hose->last_busno = 0; - - /* PCI I/O space */ - pci_set_region(hose->regions + reg_num++, - 0x00000000, - PCIL0_IOBASE, - 0x10000, - PCI_REGION_IO); - - /* PCI memory space */ - pci_set_region(hose->regions + reg_num++, - CONFIG_SYS_PCI_TARGBASE, - CONFIG_SYS_PCI_MEMBASE, -#ifdef CONFIG_SYS_PCI_MEMSIZE - CONFIG_SYS_PCI_MEMSIZE, -#else - 0x10000000, -#endif - PCI_REGION_MEM ); - -#if defined(CONFIG_PCI_SYS_MEM_BUS) && defined(CONFIG_PCI_SYS_MEM_PHYS) && \ - defined(CONFIG_PCI_SYS_MEM_SIZE) - /* System memory space */ - pci_set_region(hose->regions + reg_num++, - CONFIG_PCI_SYS_MEM_BUS, - CONFIG_PCI_SYS_MEM_PHYS, - CONFIG_PCI_SYS_MEM_SIZE, - PCI_REGION_MEM | PCI_REGION_SYS_MEMORY ); -#endif - - hose->region_count = reg_num; - - pci_setup_indirect(hose, PCIL0_CFGADR, PCIL0_CFGDATA); - - /* Let board change/modify hose & do initial checks */ - if (pci_pre_init(hose) == 0) { - printf("PCI: Board-specific initialization failed.\n"); - printf("PCI: Configuration aborted.\n"); - return -1; - } - - pci_register_hose( hose ); - - /*--------------------------------------------------------------------------+ - * PCI target init - *--------------------------------------------------------------------------*/ -#if defined(CONFIG_SYS_PCI_TARGET_INIT) - pci_target_init(hose); /* Let board setup pci target */ -#else - out16r( PCIL0_SBSYSVID, CONFIG_SYS_PCI_SUBSYS_VENDORID ); - out16r( PCIL0_SBSYSID, CONFIG_SYS_PCI_SUBSYS_ID ); - out16r( PCIL0_CLS, 0x00060000 ); /* Bridge, host bridge */ -#endif - -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) - out32r( PCIL0_BRDGOPT1, 0x04000060 ); /* PLB Rq pri highest */ - out32r( PCIL0_BRDGOPT2, in32(PCIL0_BRDGOPT2) | 0x83 ); /* Enable host config, clear Timeout, ensure int src1 */ -#elif defined(PCIL0_BRDGOPT1) - out32r( PCIL0_BRDGOPT1, 0x10000060 ); /* PLB Rq pri highest */ - out32r( PCIL0_BRDGOPT2, in32(PCIL0_BRDGOPT2) | 1 ); /* Enable host config */ -#endif - - /*--------------------------------------------------------------------------+ - * PCI master init: default is one 256MB region for PCI memory: - * 0x3_00000000 - 0x3_0FFFFFFF ==> CONFIG_SYS_PCI_MEMBASE - *--------------------------------------------------------------------------*/ -#if defined(CONFIG_SYS_PCI_MASTER_INIT) - pci_master_init(hose); /* Let board setup pci master */ -#else - out32r( PCIL0_POM0SA, 0 ); /* disable */ - out32r( PCIL0_POM1SA, 0 ); /* disable */ - out32r( PCIL0_POM2SA, 0 ); /* disable */ -#if defined(CONFIG_440SPE) - out32r( PCIL0_POM0LAL, 0x10000000 ); - out32r( PCIL0_POM0LAH, 0x0000000c ); -#elif defined(CONFIG_460EX) || defined(CONFIG_460GT) - out32r( PCIL0_POM0LAL, 0x20000000 ); - out32r( PCIL0_POM0LAH, 0x0000000c ); -#else - out32r( PCIL0_POM0LAL, 0x00000000 ); - out32r( PCIL0_POM0LAH, 0x00000003 ); -#endif - out32r( PCIL0_POM0PCIAL, CONFIG_SYS_PCI_MEMBASE ); - out32r( PCIL0_POM0PCIAH, 0x00000000 ); - out32r( PCIL0_POM0SA, 0xf0000001 ); /* 256MB, enabled */ - out32r( PCIL0_STS, in32r( PCIL0_STS ) & ~0x0000fff8 ); -#endif - - /*--------------------------------------------------------------------------+ - * PCI host configuration -- we don't make any assumptions here ... the - * _board_must_indicate_ what to do -- there's just too many runtime - * scenarios in environments like cPCI, PPMC, etc. to make a determination - * based on hard-coded values or state of arbiter enable. - *--------------------------------------------------------------------------*/ - if (is_pci_host(hose)) { -#ifdef CONFIG_PCI_SCAN_SHOW - printf("PCI: Bus Dev VenId DevId Class Int\n"); -#endif -#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) && \ - !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) - out16r( PCIL0_CMD, in16r( PCIL0_CMD ) | PCI_COMMAND_MASTER); -#endif - hose->last_busno = pci_hose_scan(hose); - } - return hose->last_busno; -} -#endif - -void pci_init_board(void) -{ - int busno = 0; - - /* - * Only init PCI when either master or target functionality - * is selected. - */ -#if defined(CONFIG_SYS_PCI_MASTER_INIT) || defined(CONFIG_SYS_PCI_TARGET_INIT) - busno = pci_440_init (&ppc440_hose); -#endif -#if (defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \ - !defined(CONFIG_PCI_DISABLE_PCIE) - pcie_setup_hoses(busno + 1); -#endif -} - -#endif /* CONFIG_440 */ - -#if defined(CONFIG_405EX) -void pci_init_board(void) -{ -#ifdef CONFIG_PCI_SCAN_SHOW - printf("PCI: Bus Dev VenId DevId Class Int\n"); -#endif - pcie_setup_hoses(0); -} -#endif /* CONFIG_405EX */ - -#endif /* CONFIG_PCI */ diff --git a/arch/powerpc/cpu/ppc4xx/4xx_pcie.c b/arch/powerpc/cpu/ppc4xx/4xx_pcie.c deleted file mode 100644 index b76890e..0000000 --- a/arch/powerpc/cpu/ppc4xx/4xx_pcie.c +++ /dev/null @@ -1,1298 +0,0 @@ -/* - * (C) Copyright 2006 - 2008 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * Copyright (c) 2005 Cisco Systems. All rights reserved. - * Roland Dreier <rolandd@cisco.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -/* define DEBUG for debugging output (obviously ;-)) */ -#if 0 -#define DEBUG -#endif - -#include <common.h> -#include <pci.h> -#include <asm/ppc4xx.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <asm/errno.h> - -#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \ - defined(CONFIG_PCI) && !defined(CONFIG_PCI_DISABLE_PCIE) - -#include <asm/4xx_pcie.h> - -enum { - PTYPE_ENDPOINT = 0x0, - PTYPE_LEGACY_ENDPOINT = 0x1, - PTYPE_ROOT_PORT = 0x4, - - LNKW_X1 = 0x1, - LNKW_X4 = 0x4, - LNKW_X8 = 0x8 -}; - -static struct pci_controller pcie_hose[CONFIG_SYS_PCIE_NR_PORTS]; - -/* - * Per default, all cards are present, so we need to check if the - * link comes up. - */ -int __board_pcie_card_present(int port) -{ - return 1; -} -int board_pcie_card_present(int port) - __attribute__((weak, alias("__board_pcie_card_present"))); - -/* - * Some boards have runtime detection of the first and last PCIe - * slot used, so let's provide weak default functions for the - * common version. - */ -int __board_pcie_first(void) -{ - return 0; -} -int board_pcie_first(void) - __attribute__((weak, alias("__board_pcie_first"))); - -int __board_pcie_last(void) -{ - return CONFIG_SYS_PCIE_NR_PORTS - 1; -} -int board_pcie_last(void) - __attribute__((weak, alias("__board_pcie_last"))); - -void __board_pcie_setup_port(int port, int rootpoint) -{ - /* noting in this weak default implementation */ -} -void board_pcie_setup_port(int port, int rootpoint) - __attribute__((weak, alias("__board_pcie_setup_port"))); - -void pcie_setup_hoses(int busno) -{ - struct pci_controller *hose; - int i, bus; - int ret = 0; - char *env; - unsigned int delay; - int first = board_pcie_first(); - int last = board_pcie_last(); - - /* - * Assume we're called after the PCI(X) hose(s) are initialized, - * which takes bus ID 0... and therefore start numbering PCIe's - * from the next number. - */ - bus = busno; - - for (i = first; i <= last; i++) { - /* - * Some boards (e.g. Katmai) can detects via hardware - * if a PCIe card is plugged, so let's check this. - */ - if (!board_pcie_card_present(i)) - continue; - - if (is_end_point(i)) { - board_pcie_setup_port(i, 0); - ret = ppc4xx_init_pcie_endport(i); - } else { - board_pcie_setup_port(i, 1); - ret = ppc4xx_init_pcie_rootport(i); - } - if (ret == -ENODEV) - continue; - if (ret) { - printf("PCIE%d: initialization as %s failed\n", i, - is_end_point(i) ? "endpoint" : "root-complex"); - continue; - } - - hose = &pcie_hose[i]; - hose->first_busno = bus; - hose->last_busno = bus; - hose->current_busno = bus; - - /* setup mem resource */ - pci_set_region(hose->regions + 0, - CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE, - CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE, - CONFIG_SYS_PCIE_MEMSIZE, - PCI_REGION_MEM); - hose->region_count = 1; - pci_register_hose(hose); - - if (is_end_point(i)) { - ppc4xx_setup_pcie_endpoint(hose, i); - /* - * Reson for no scanning is endpoint can not generate - * upstream configuration accesses. - */ - } else { - ppc4xx_setup_pcie_rootpoint(hose, i); - env = getenv ("pciscandelay"); - if (env != NULL) { - delay = simple_strtoul(env, NULL, 10); - if (delay > 5) - printf("Warning, expect noticable delay before " - "PCIe scan due to 'pciscandelay' value!\n"); - mdelay(delay * 1000); - } - - /* - * Config access can only go down stream - */ - hose->last_busno = pci_hose_scan(hose); - bus = hose->last_busno + 1; - } - } -} - -static int validate_endpoint(struct pci_controller *hose) -{ - if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE0_CFGBASE) - return (is_end_point(0)); - else if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE1_CFGBASE) - return (is_end_point(1)); -#if CONFIG_SYS_PCIE_NR_PORTS > 2 - else if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE2_CFGBASE) - return (is_end_point(2)); -#endif - - return 0; -} - -static u8* pcie_get_base(struct pci_controller *hose, unsigned int devfn) -{ - u8 *base = (u8*)hose->cfg_data; - - /* use local configuration space for the first bus */ - if (PCI_BUS(devfn) == 0) { - if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE0_CFGBASE) - base = (u8*)CONFIG_SYS_PCIE0_XCFGBASE; - if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE1_CFGBASE) - base = (u8*)CONFIG_SYS_PCIE1_XCFGBASE; -#if CONFIG_SYS_PCIE_NR_PORTS > 2 - if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE2_CFGBASE) - base = (u8*)CONFIG_SYS_PCIE2_XCFGBASE; -#endif - } - - return base; -} - -static void pcie_dmer_disable(void) -{ - mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE), - mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) | GPL_DMER_MASK_DISA); - mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE), - mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) | GPL_DMER_MASK_DISA); -#if CONFIG_SYS_PCIE_NR_PORTS > 2 - mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE), - mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) | GPL_DMER_MASK_DISA); -#endif -} - -static void pcie_dmer_enable(void) -{ - mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE0_BASE), - mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) & ~GPL_DMER_MASK_DISA); - mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE1_BASE), - mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) & ~GPL_DMER_MASK_DISA); -#if CONFIG_SYS_PCIE_NR_PORTS > 2 - mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE2_BASE), - mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) & ~GPL_DMER_MASK_DISA); -#endif -} - -static int pcie_read_config(struct pci_controller *hose, unsigned int devfn, - int offset, int len, u32 *val) { - - u8 *address; - *val = 0; - - if (validate_endpoint(hose)) - return 0; /* No upstream config access */ - - /* - * Bus numbers are relative to hose->first_busno - */ - devfn -= PCI_BDF(hose->first_busno, 0, 0); - - /* - * NOTICE: configuration space ranges are currenlty mapped only for - * the first 16 buses, so such limit must be imposed. In case more - * buses are required the TLB settings in board/amcc/<board>/init.S - * need to be altered accordingly (one bus takes 1 MB of memory space). - */ - if (PCI_BUS(devfn) >= 16) - return 0; - - /* - * Only single device/single function is supported for the primary and - * secondary buses of the 440SPe host bridge. - */ - if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) && - ((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1))) - return 0; - - address = pcie_get_base(hose, devfn); - offset += devfn << 4; - - /* - * Reading from configuration space of non-existing device can - * generate transaction errors. For the read duration we suppress - * assertion of machine check exceptions to avoid those. - */ - pcie_dmer_disable (); - - debug("%s: cfg_data=%08x offset=%08x\n", __func__, hose->cfg_data, offset); - switch (len) { - case 1: - *val = in_8(hose->cfg_data + offset); - break; - case 2: - *val = in_le16((u16 *)(hose->cfg_data + offset)); - break; - default: - *val = in_le32((u32*)(hose->cfg_data + offset)); - break; - } - - pcie_dmer_enable (); - - return 0; -} - -static int pcie_write_config(struct pci_controller *hose, unsigned int devfn, - int offset, int len, u32 val) { - - u8 *address; - - if (validate_endpoint(hose)) - return 0; /* No upstream config access */ - - /* - * Bus numbers are relative to hose->first_busno - */ - devfn -= PCI_BDF(hose->first_busno, 0, 0); - - /* - * Same constraints as in pcie_read_config(). - */ - if (PCI_BUS(devfn) >= 16) - return 0; - - if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) && - ((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1))) - return 0; - - address = pcie_get_base(hose, devfn); - offset += devfn << 4; - - /* - * Suppress MCK exceptions, similar to pcie_read_config() - */ - pcie_dmer_disable (); - - switch (len) { - case 1: - out_8(hose->cfg_data + offset, val); - break; - case 2: - out_le16((u16 *)(hose->cfg_data + offset), val); - break; - default: - out_le32((u32 *)(hose->cfg_data + offset), val); - break; - } - - pcie_dmer_enable (); - - return 0; -} - -int pcie_read_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 *val) -{ - u32 v; - int rv; - - rv = pcie_read_config(hose, dev, offset, 1, &v); - *val = (u8)v; - return rv; -} - -int pcie_read_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 *val) -{ - u32 v; - int rv; - - rv = pcie_read_config(hose, dev, offset, 2, &v); - *val = (u16)v; - return rv; -} - -int pcie_read_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 *val) -{ - u32 v; - int rv; - - rv = pcie_read_config(hose, dev, offset, 3, &v); - *val = (u32)v; - return rv; -} - -int pcie_write_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 val) -{ - return pcie_write_config(hose,(u32)dev,offset,1,val); -} - -int pcie_write_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 val) -{ - return pcie_write_config(hose,(u32)dev,offset,2,(u32 )val); -} - -int pcie_write_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 val) -{ - return pcie_write_config(hose,(u32)dev,offset,3,(u32 )val); -} - -#if defined(CONFIG_440SPE) -static void ppc4xx_setup_utl(u32 port) { - - volatile void *utl_base = NULL; - - /* - * Map UTL registers - */ - switch (port) { - case 0: - mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c); - mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x20000000); - mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); - mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800); - break; - - case 1: - mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c); - mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x20001000); - mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); - mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800); - break; - - case 2: - mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c); - mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x20002000); - mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001); - mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800); - break; - } - utl_base = (unsigned int *)(CONFIG_SYS_PCIE_BASE + 0x1000 * port); - - /* - * Set buffer allocations and then assert VRB and TXE. - */ - out_be32(utl_base + PEUTL_OUTTR, 0x08000000); - out_be32(utl_base + PEUTL_INTR, 0x02000000); - out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000); - out_be32(utl_base + PEUTL_PBBSZ, 0x53000000); - out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000); - out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000); - out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); - out_be32(utl_base + PEUTL_PCTL, 0x80800066); -} - -static int check_error(void) -{ - u32 valPE0, valPE1, valPE2; - int err = 0; - - /* SDR0_PEGPLLLCT1 reset */ - if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) - printf("PCIE: SDR0_PEGPLLLCT1 reset error 0x%x\n", valPE0); - - valPE0 = SDR_READ(PESDR0_RCSSET); - valPE1 = SDR_READ(PESDR1_RCSSET); - valPE2 = SDR_READ(PESDR2_RCSSET); - - /* SDR0_PExRCSSET rstgu */ - if (!(valPE0 & 0x01000000) || - !(valPE1 & 0x01000000) || - !(valPE2 & 0x01000000)) { - printf("PCIE: SDR0_PExRCSSET rstgu error\n"); - err = -1; - } - - /* SDR0_PExRCSSET rstdl */ - if (!(valPE0 & 0x00010000) || - !(valPE1 & 0x00010000) || - !(valPE2 & 0x00010000)) { - printf("PCIE: SDR0_PExRCSSET rstdl error\n"); - err = -1; - } - - /* SDR0_PExRCSSET rstpyn */ - if ((valPE0 & 0x00001000) || - (valPE1 & 0x00001000) || - (valPE2 & 0x00001000)) { - printf("PCIE: SDR0_PExRCSSET rstpyn error\n"); - err = -1; - } - - /* SDR0_PExRCSSET hldplb */ - if ((valPE0 & 0x10000000) || - (valPE1 & 0x10000000) || - (valPE2 & 0x10000000)) { - printf("PCIE: SDR0_PExRCSSET hldplb error\n"); - err = -1; - } - - /* SDR0_PExRCSSET rdy */ - if ((valPE0 & 0x00100000) || - (valPE1 & 0x00100000) || - (valPE2 & 0x00100000)) { - printf("PCIE: SDR0_PExRCSSET rdy error\n"); - err = -1; - } - - /* SDR0_PExRCSSET shutdown */ - if ((valPE0 & 0x00000100) || - (valPE1 & 0x00000100) || - (valPE2 & 0x00000100)) { - printf("PCIE: SDR0_PExRCSSET shutdown error\n"); - err = -1; - } - return err; -} - -/* - * Initialize PCI Express core - */ -int ppc4xx_init_pcie(void) -{ - int time_out = 20; - - /* Set PLL clock receiver to LVPECL */ - SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28); - - if (check_error()) { - printf("ERROR: failed to set PCIe reference clock receiver --" - "PESDR0_PLLLCT1 = 0x%08x\n", SDR_READ(PESDR0_PLLLCT1)); - - return -1; - } - - /* Did resistance calibration work? */ - if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000)) { - printf("ERROR: PCIe resistance calibration failed --" - "PESDR0_PLLLCT2 = 0x%08x\n", SDR_READ(PESDR0_PLLLCT2)); - - return -1; - } - /* De-assert reset of PCIe PLL, wait for lock */ - SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24)); - udelay(300); /* 300 uS is maximum time lock should take */ - - while (time_out) { - if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) { - time_out--; - udelay(20); /* Wait 20 uS more if needed */ - } else - break; - } - if (!time_out) { - printf("ERROR: PCIe PLL VCO output not locked to ref clock --" - "PESDR0_PLLLCTS=0x%08x\n", SDR_READ(PESDR0_PLLLCT3)); - - return -1; - } - return 0; -} -#endif - -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) -static void ppc4xx_setup_utl(u32 port) -{ - volatile void *utl_base = NULL; - - /* - * Map UTL registers at 0x0801_n000 (4K 0xfff mask) PEGPLn_REGMSK - */ - switch (port) { - case 0: - mtdcr(DCRN_PEGPL_REGBAH(PCIE0), U64_TO_U32_HIGH(CONFIG_SYS_PCIE0_UTLBASE)); - mtdcr(DCRN_PEGPL_REGBAL(PCIE0), U64_TO_U32_LOW(CONFIG_SYS_PCIE0_UTLBASE)); - mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* BAM 11100000=4KB */ - mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0); - break; - - case 1: - mtdcr(DCRN_PEGPL_REGBAH(PCIE1), U64_TO_U32_HIGH(CONFIG_SYS_PCIE0_UTLBASE)); - mtdcr(DCRN_PEGPL_REGBAL(PCIE1), U64_TO_U32_LOW(CONFIG_SYS_PCIE0_UTLBASE) - + 0x1000); - mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* BAM 11100000=4KB */ - mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0); - break; - } - utl_base = (unsigned int *)(CONFIG_SYS_PCIE_BASE + 0x1000 * port); - - /* - * Set buffer allocations and then assert VRB and TXE. - */ - out_be32(utl_base + PEUTL_PBCTL, 0x0800000c); /* PLBME, CRRE */ - out_be32(utl_base + PEUTL_OUTTR, 0x08000000); - out_be32(utl_base + PEUTL_INTR, 0x02000000); - out_be32(utl_base + PEUTL_OPDBSZ, 0x04000000); /* OPD = 512 Bytes */ - out_be32(utl_base + PEUTL_PBBSZ, 0x00000000); /* Max 512 Bytes */ - out_be32(utl_base + PEUTL_IPHBSZ, 0x02000000); - out_be32(utl_base + PEUTL_IPDBSZ, 0x04000000); /* IPD = 512 Bytes */ - out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); - out_be32(utl_base + PEUTL_PCTL, 0x80800066); /* VRB,TXE,timeout=default */ -} - -/* - * TODO: double check PCI express SDR based on the latest user manual - * Some registers specified here no longer exist.. has to be - * updated based on the final EAS spec. - */ -static int check_error(void) -{ - u32 valPE0, valPE1; - int err = 0; - - valPE0 = SDR_READ(SDRN_PESDR_RCSSET(0)); - valPE1 = SDR_READ(SDRN_PESDR_RCSSET(1)); - - /* SDR0_PExRCSSET rstgu */ - if (!(valPE0 & PESDRx_RCSSET_RSTGU) || !(valPE1 & PESDRx_RCSSET_RSTGU)) { - printf("PCIE: SDR0_PExRCSSET rstgu error\n"); - err = -1; - } - - /* SDR0_PExRCSSET rstdl */ - if (!(valPE0 & PESDRx_RCSSET_RSTDL) || !(valPE1 & PESDRx_RCSSET_RSTDL)) { - printf("PCIE: SDR0_PExRCSSET rstdl error\n"); - err = -1; - } - - /* SDR0_PExRCSSET rstpyn */ - if ((valPE0 & PESDRx_RCSSET_RSTPYN) || (valPE1 & PESDRx_RCSSET_RSTPYN)) { - printf("PCIE: SDR0_PExRCSSET rstpyn error\n"); - err = -1; - } - - /* SDR0_PExRCSSET hldplb */ - if ((valPE0 & PESDRx_RCSSET_HLDPLB) || (valPE1 & PESDRx_RCSSET_HLDPLB)) { - printf("PCIE: SDR0_PExRCSSET hldplb error\n"); - err = -1; - } - - /* SDR0_PExRCSSET rdy */ - if ((valPE0 & PESDRx_RCSSET_RDY) || (valPE1 & PESDRx_RCSSET_RDY)) { - printf("PCIE: SDR0_PExRCSSET rdy error\n"); - err = -1; - } - - return err; -} - -/* - * Initialize PCI Express core as described in User Manual - * TODO: double check PE SDR PLL Register with the updated user manual. - */ -int ppc4xx_init_pcie(void) -{ - if (check_error()) - return -1; - - return 0; -} -#endif /* CONFIG_460EX */ - -#if defined(CONFIG_405EX) -static void ppc4xx_setup_utl(u32 port) -{ - u32 utl_base; - - /* - * Map UTL registers at 0xef4f_n000 (4K 0xfff mask) PEGPLn_REGMSK - */ - switch (port) { - case 0: - mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x00000000); - mtdcr(DCRN_PEGPL_REGBAL(PCIE0), CONFIG_SYS_PCIE0_UTLBASE); - mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* 4k region, valid */ - mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0); - break; - - case 1: - mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x00000000); - mtdcr(DCRN_PEGPL_REGBAL(PCIE1), CONFIG_SYS_PCIE1_UTLBASE); - mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* 4k region, valid */ - mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0); - - break; - } - utl_base = (port==0) ? CONFIG_SYS_PCIE0_UTLBASE : CONFIG_SYS_PCIE1_UTLBASE; - - /* - * Set buffer allocations and then assert VRB and TXE. - */ - out_be32((u32 *)(utl_base + PEUTL_OUTTR), 0x02000000); - out_be32((u32 *)(utl_base + PEUTL_INTR), 0x02000000); - out_be32((u32 *)(utl_base + PEUTL_OPDBSZ), 0x04000000); - out_be32((u32 *)(utl_base + PEUTL_PBBSZ), 0x21000000); - out_be32((u32 *)(utl_base + PEUTL_IPHBSZ), 0x02000000); - out_be32((u32 *)(utl_base + PEUTL_IPDBSZ), 0x04000000); - out_be32((u32 *)(utl_base + PEUTL_RCIRQEN), 0x00f00000); - out_be32((u32 *)(utl_base + PEUTL_PCTL), 0x80800066); - - out_be32((u32 *)(utl_base + PEUTL_PBCTL), 0x0800000c); - out_be32((u32 *)(utl_base + PEUTL_RCSTA), - in_be32((u32 *)(utl_base + PEUTL_RCSTA)) | 0x000040000); -} - -int ppc4xx_init_pcie(void) -{ - /* - * Nothing to do on 405EX - */ - return 0; -} -#endif /* CONFIG_405EX */ - -/* - * Board-specific pcie initialization - * Platform code can reimplement ppc4xx_init_pcie_port_hw() if needed - */ - -/* - * Initialize various parts of the PCI Express core for our port: - * - * - Set as a root port and enable max width - * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). - * - Set up UTL configuration. - * - Increase SERDES drive strength to levels suggested by AMCC. - * - De-assert RSTPYN, RSTDL and RSTGU. - * - * NOTICE for 440SPE revB chip: PESDRn_UTLSET2 is not set - we leave it - * with default setting 0x11310000. The register has new fields, - * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core - * hang. - */ -#if defined(CONFIG_440SPE) -int __ppc4xx_init_pcie_port_hw(int port, int rootport) -{ - u32 val = 1 << 24; - u32 utlset1; - - if (rootport) { - val = PTYPE_ROOT_PORT << 20; - utlset1 = 0x21222222; - } else { - val = PTYPE_LEGACY_ENDPOINT << 20; - utlset1 = 0x20222222; - } - - if (port == 0) - val |= LNKW_X8 << 12; - else - val |= LNKW_X4 << 12; - - SDR_WRITE(SDRN_PESDR_DLPSET(port), val); - SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1); - if (!ppc440spe_revB()) - SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x11000000); - SDR_WRITE(SDRN_PESDR_HSSL0SET1(port), 0x35000000); - SDR_WRITE(SDRN_PESDR_HSSL1SET1(port), 0x35000000); - SDR_WRITE(SDRN_PESDR_HSSL2SET1(port), 0x35000000); - SDR_WRITE(SDRN_PESDR_HSSL3SET1(port), 0x35000000); - if (port == 0) { - SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); - } - SDR_WRITE(SDRN_PESDR_RCSSET(port), (SDR_READ(SDRN_PESDR_RCSSET(port)) & - ~(1 << 24 | 1 << 16)) | 1 << 12); - - return 0; -} -#endif /* CONFIG_440SPE */ - -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) -int __ppc4xx_init_pcie_port_hw(int port, int rootport) -{ - u32 val; - u32 utlset1; - - if (rootport) - val = PTYPE_ROOT_PORT << 20; - else - val = PTYPE_LEGACY_ENDPOINT << 20; - - if (port == 0) { - val |= LNKW_X1 << 12; - utlset1 = 0x20000000; - } else { - val |= LNKW_X4 << 12; - utlset1 = 0x20101101; - } - - SDR_WRITE(SDRN_PESDR_DLPSET(port), val); - SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1); - SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01210000); - - switch (port) { - case 0: - SDR_WRITE(PESDR0_L0CDRCTL, 0x00003230); - SDR_WRITE(PESDR0_L0DRV, 0x00000130); - SDR_WRITE(PESDR0_L0CLK, 0x00000006); - - SDR_WRITE(PESDR0_PHY_CTL_RST,0x10000000); - break; - - case 1: - SDR_WRITE(PESDR1_L0CDRCTL, 0x00003230); - SDR_WRITE(PESDR1_L1CDRCTL, 0x00003230); - SDR_WRITE(PESDR1_L2CDRCTL, 0x00003230); - SDR_WRITE(PESDR1_L3CDRCTL, 0x00003230); - SDR_WRITE(PESDR1_L0DRV, 0x00000130); - SDR_WRITE(PESDR1_L1DRV, 0x00000130); - SDR_WRITE(PESDR1_L2DRV, 0x00000130); - SDR_WRITE(PESDR1_L3DRV, 0x00000130); - SDR_WRITE(PESDR1_L0CLK, 0x00000006); - SDR_WRITE(PESDR1_L1CLK, 0x00000006); - SDR_WRITE(PESDR1_L2CLK, 0x00000006); - SDR_WRITE(PESDR1_L3CLK, 0x00000006); - - SDR_WRITE(PESDR1_PHY_CTL_RST,0x10000000); - break; - } - - SDR_WRITE(SDRN_PESDR_RCSSET(port), SDR_READ(SDRN_PESDR_RCSSET(port)) | - (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN)); - - /* Poll for PHY reset */ - switch (port) { - case 0: - while (!(SDR_READ(PESDR0_RSTSTA) & 0x1)) - udelay(10); - break; - case 1: - while (!(SDR_READ(PESDR1_RSTSTA) & 0x1)) - udelay(10); - break; - } - - SDR_WRITE(SDRN_PESDR_RCSSET(port), - (SDR_READ(SDRN_PESDR_RCSSET(port)) & - ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) | - PESDRx_RCSSET_RSTPYN); - - return 0; -} -#endif /* CONFIG_440SPE */ - -#if defined(CONFIG_405EX) -int __ppc4xx_init_pcie_port_hw(int port, int rootport) -{ - u32 val; - - if (rootport) - val = 0x00401000; - else - val = 0x00101000; - - SDR_WRITE(SDRN_PESDR_DLPSET(port), val); - SDR_WRITE(SDRN_PESDR_UTLSET1(port), 0x00000000); - SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01010000); - SDR_WRITE(SDRN_PESDR_PHYSET1(port), 0x720F0000); - SDR_WRITE(SDRN_PESDR_PHYSET2(port), 0x70600003); - - /* Assert the PE0_PHY reset */ - SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01010000); - udelay(1000); - - /* deassert the PE0_hotreset */ - if (is_end_point(port)) - SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01111000); - else - SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01101000); - - /* poll for phy !reset */ - while (!(SDR_READ(SDRN_PESDR_PHYSTA(port)) & 0x00001000)) - ; - - /* deassert the PE0_gpl_utl_reset */ - SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x00101000); - - if (port == 0) - mtdcr(DCRN_PEGPL_CFG(PCIE0), 0x10000000); /* guarded on */ - else - mtdcr(DCRN_PEGPL_CFG(PCIE1), 0x10000000); /* guarded on */ - - return 0; -} -#endif /* CONFIG_405EX */ - -int ppc4xx_init_pcie_port_hw(int port, int rootport) -__attribute__((weak, alias("__ppc4xx_init_pcie_port_hw"))); - -/* - * We map PCI Express configuration access into the 512MB regions - * - * NOTICE: revB is very strict about PLB real addressess and ranges to - * be mapped for config space; it seems to only work with d_nnnn_nnnn - * range (hangs the core upon config transaction attempts when set - * otherwise) while revA uses c_nnnn_nnnn. - * - * For 440SPe revA: - * PCIE0: 0xc_4000_0000 - * PCIE1: 0xc_8000_0000 - * PCIE2: 0xc_c000_0000 - * - * For 440SPe revB: - * PCIE0: 0xd_0000_0000 - * PCIE1: 0xd_2000_0000 - * PCIE2: 0xd_4000_0000 - * - * For 405EX: - * PCIE0: 0xa000_0000 - * PCIE1: 0xc000_0000 - * - * For 460EX/GT: - * PCIE0: 0xd_0000_0000 - * PCIE1: 0xd_2000_0000 - */ -static inline u64 ppc4xx_get_cfgaddr(int port) -{ -#if defined(CONFIG_405EX) - if (port == 0) - return (u64)CONFIG_SYS_PCIE0_CFGBASE; - else - return (u64)CONFIG_SYS_PCIE1_CFGBASE; -#endif -#if defined(CONFIG_440SPE) - if (ppc440spe_revB()) { - switch (port) { - default: /* to satisfy compiler */ - case 0: - return 0x0000000d00000000ULL; - case 1: - return 0x0000000d20000000ULL; - case 2: - return 0x0000000d40000000ULL; - } - } else { - switch (port) { - default: /* to satisfy compiler */ - case 0: - return 0x0000000c40000000ULL; - case 1: - return 0x0000000c80000000ULL; - case 2: - return 0x0000000cc0000000ULL; - } - } -#endif -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) - if (port == 0) - return 0x0000000d00000000ULL; - else - return 0x0000000d20000000ULL; -#endif -} - -/* - * 4xx boards as endpoint and root point setup - * and - * testing inbound and out bound windows - * - * 4xx boards can be plugged into another 4xx boards or you can get PCI-E - * cable which can be used to setup loop back from one port to another port. - * Please rememeber that unless there is a endpoint plugged in to root port it - * will not initialize. It is the same in case of endpoint , unless there is - * root port attached it will not initialize. - * - * In this release of software all the PCI-E ports are configured as either - * endpoint or rootpoint.In future we will have support for selective ports - * setup as endpoint and root point in single board. - * - * Once your board came up as root point , you can verify by reading - * /proc/bus/pci/devices. Where you can see the configuration registers - * of endpoint device attached to the port. - * - * Enpoint cofiguration can be verified by connecting 4xx board to any - * host or another 4xx board. Then try to scan the device. In case of - * linux use "lspci" or appripriate os command. - * - * How do I verify the inbound and out bound windows ? (4xx to 4xx) - * in this configuration inbound and outbound windows are setup to access - * sram memroy area. SRAM is at 0x4 0000 0000 , on PLB bus. This address - * is mapped at 0x90000000. From u-boot prompt write data 0xb000 0000, - * This is waere your POM(PLB out bound memory window) mapped. then - * read the data from other 4xx board's u-boot prompt at address - * 0x9000 0000(SRAM). Data should match. - * In case of inbound , write data to u-boot command prompt at 0xb000 0000 - * which is mapped to 0x4 0000 0000. Now on rootpoint yucca u-boot prompt check - * data at 0x9000 0000(SRAM).Data should match. - */ -int ppc4xx_init_pcie_port(int port, int rootport) -{ - static int core_init; - volatile u32 val = 0; - int attempts; - u64 addr; - u32 low, high; - - if (!core_init) { - if (ppc4xx_init_pcie()) - return -1; - ++core_init; - } - - /* - * Initialize various parts of the PCI Express core for our port - */ - ppc4xx_init_pcie_port_hw(port, rootport); - - /* - * Notice: the following delay has critical impact on device - * initialization - if too short (<50ms) the link doesn't get up. - */ - mdelay(100); - - val = SDR_READ(SDRN_PESDR_RCSSTS(port)); - if (val & (1 << 20)) { - printf("PCIE%d: PGRST failed %08x\n", port, val); - return -1; - } - - /* - * Verify link is up - */ - val = SDR_READ(SDRN_PESDR_LOOP(port)); - if (!(val & 0x00001000)) { - printf("PCIE%d: link is not up.\n", port); - return -ENODEV; - } - - /* - * Setup UTL registers - but only on revA! - * We use default settings for revB chip. - */ - if (!ppc440spe_revB()) - ppc4xx_setup_utl(port); - - /* - * We map PCI Express configuration access into the 512MB regions - */ - addr = ppc4xx_get_cfgaddr(port); - low = U64_TO_U32_LOW(addr); - high = U64_TO_U32_HIGH(addr); - - switch (port) { - case 0: - mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), high); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), low); - mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */ - break; - case 1: - mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), high); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), low); - mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */ - break; -#if CONFIG_SYS_PCIE_NR_PORTS > 2 - case 2: - mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), high); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), low); - mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */ - break; -#endif - } - - /* - * Check for VC0 active and assert RDY. - */ - attempts = 10; - while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 16))) { - if (!(attempts--)) { - printf("PCIE%d: VC0 not active\n", port); - return -1; - } - mdelay(1000); - } - SDR_WRITE(SDRN_PESDR_RCSSET(port), - SDR_READ(SDRN_PESDR_RCSSET(port)) | 1 << 20); - mdelay(100); - - return 0; -} - -int ppc4xx_init_pcie_rootport(int port) -{ - return ppc4xx_init_pcie_port(port, 1); -} - -int ppc4xx_init_pcie_endport(int port) -{ - return ppc4xx_init_pcie_port(port, 0); -} - -void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port) -{ - volatile void *mbase = NULL; - volatile void *rmbase = NULL; - - pci_set_ops(hose, - pcie_read_config_byte, - pcie_read_config_word, - pcie_read_config_dword, - pcie_write_config_byte, - pcie_write_config_word, - pcie_write_config_dword); - - switch (port) { - case 0: - mbase = (u32 *)CONFIG_SYS_PCIE0_XCFGBASE; - rmbase = (u32 *)CONFIG_SYS_PCIE0_CFGBASE; - hose->cfg_data = (u8 *)CONFIG_SYS_PCIE0_CFGBASE; - break; - case 1: - mbase = (u32 *)CONFIG_SYS_PCIE1_XCFGBASE; - rmbase = (u32 *)CONFIG_SYS_PCIE1_CFGBASE; - hose->cfg_data = (u8 *)CONFIG_SYS_PCIE1_CFGBASE; - break; -#if CONFIG_SYS_PCIE_NR_PORTS > 2 - case 2: - mbase = (u32 *)CONFIG_SYS_PCIE2_XCFGBASE; - rmbase = (u32 *)CONFIG_SYS_PCIE2_CFGBASE; - hose->cfg_data = (u8 *)CONFIG_SYS_PCIE2_CFGBASE; - break; -#endif - } - - /* - * Set bus numbers on our root port - */ - out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); - out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1); - out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1); - - /* - * Set up outbound translation to hose->mem_space from PLB - * addresses at an offset of 0xd_0000_0000. We set the low - * bits of the mask to 11 to turn off splitting into 8 - * subregions and to enable the outbound translation. - */ - out_le32(mbase + PECFG_POM0LAH, 0x00000000); - out_le32(mbase + PECFG_POM0LAL, CONFIG_SYS_PCIE_MEMBASE + - port * CONFIG_SYS_PCIE_MEMSIZE); - debug("PECFG_POM0LA=%08x.%08x\n", in_le32(mbase + PECFG_POM0LAH), - in_le32(mbase + PECFG_POM0LAL)); - - switch (port) { - case 0: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CONFIG_SYS_PCIE_ADDR_HIGH); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CONFIG_SYS_PCIE_MEMBASE + - port * CONFIG_SYS_PCIE_MEMSIZE); - mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff); - mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), - ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3); - debug("0:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n", - mfdcr(DCRN_PEGPL_OMR1BAH(PCIE0)), - mfdcr(DCRN_PEGPL_OMR1BAL(PCIE0)), - mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE0)), - mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE0))); - break; - case 1: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CONFIG_SYS_PCIE_ADDR_HIGH); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CONFIG_SYS_PCIE_MEMBASE + - port * CONFIG_SYS_PCIE_MEMSIZE); - mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff); - mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), - ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3); - debug("1:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n", - mfdcr(DCRN_PEGPL_OMR1BAH(PCIE1)), - mfdcr(DCRN_PEGPL_OMR1BAL(PCIE1)), - mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE1)), - mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE1))); - break; -#if CONFIG_SYS_PCIE_NR_PORTS > 2 - case 2: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CONFIG_SYS_PCIE_ADDR_HIGH); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CONFIG_SYS_PCIE_MEMBASE + - port * CONFIG_SYS_PCIE_MEMSIZE); - mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff); - mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2), - ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3); - debug("2:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n", - mfdcr(DCRN_PEGPL_OMR1BAH(PCIE2)), - mfdcr(DCRN_PEGPL_OMR1BAL(PCIE2)), - mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE2)), - mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE2))); - break; -#endif - } - - /* Set up 4GB inbound memory window at 0 */ - out_le32(mbase + PCI_BASE_ADDRESS_0, 0); - out_le32(mbase + PCI_BASE_ADDRESS_1, 0); - out_le32(mbase + PECFG_BAR0HMPA, 0x7ffffff); - out_le32(mbase + PECFG_BAR0LMPA, 0); - - out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); - out_le32(mbase + PECFG_PIM01SAL, 0x00000000); - out_le32(mbase + PECFG_PIM0LAL, 0); - out_le32(mbase + PECFG_PIM0LAH, 0); - out_le32(mbase + PECFG_PIM1LAL, 0x00000000); - out_le32(mbase + PECFG_PIM1LAH, 0x00000004); - out_le32(mbase + PECFG_PIMEN, 0x1); - - /* Enable I/O, Mem, and Busmaster cycles */ - out_le16((u16 *)(mbase + PCI_COMMAND), - in_le16((u16 *)(mbase + PCI_COMMAND)) | - PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - - /* Set Device and Vendor Id */ - out_le16(mbase + 0x200, 0xaaa0 + port); - out_le16(mbase + 0x202, 0xbed0 + port); - - /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ - out_le32(mbase + 0x208, 0x06040001); - - printf("PCIE%d: successfully set as root-complex\n", port); -} - -int ppc4xx_setup_pcie_endpoint(struct pci_controller *hose, int port) -{ - volatile void *mbase = NULL; - int attempts = 0; - - pci_set_ops(hose, - pcie_read_config_byte, - pcie_read_config_word, - pcie_read_config_dword, - pcie_write_config_byte, - pcie_write_config_word, - pcie_write_config_dword); - - switch (port) { - case 0: - mbase = (u32 *)CONFIG_SYS_PCIE0_XCFGBASE; - hose->cfg_data = (u8 *)CONFIG_SYS_PCIE0_CFGBASE; - break; - case 1: - mbase = (u32 *)CONFIG_SYS_PCIE1_XCFGBASE; - hose->cfg_data = (u8 *)CONFIG_SYS_PCIE1_CFGBASE; - break; -#if defined(CONFIG_SYS_PCIE2_CFGBASE) - case 2: - mbase = (u32 *)CONFIG_SYS_PCIE2_XCFGBASE; - hose->cfg_data = (u8 *)CONFIG_SYS_PCIE2_CFGBASE; - break; -#endif - } - - /* - * Set up outbound translation to hose->mem_space from PLB - * addresses at an offset of 0xd_0000_0000. We set the low - * bits of the mask to 11 to turn off splitting into 8 - * subregions and to enable the outbound translation. - */ - out_le32(mbase + PECFG_POM0LAH, 0x00001ff8); - out_le32(mbase + PECFG_POM0LAL, 0x00001000); - - switch (port) { - case 0: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CONFIG_SYS_PCIE_ADDR_HIGH); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CONFIG_SYS_PCIE_MEMBASE + - port * CONFIG_SYS_PCIE_MEMSIZE); - mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff); - mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), - ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3); - break; - case 1: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CONFIG_SYS_PCIE_ADDR_HIGH); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CONFIG_SYS_PCIE_MEMBASE + - port * CONFIG_SYS_PCIE_MEMSIZE); - mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff); - mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), - ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3); - break; -#if CONFIG_SYS_PCIE_NR_PORTS > 2 - case 2: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CONFIG_SYS_PCIE_ADDR_HIGH); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CONFIG_SYS_PCIE_MEMBASE + - port * CONFIG_SYS_PCIE_MEMSIZE); - mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff); - mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2), - ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3); - break; -#endif - } - - /* Set up 64MB inbound memory window at 0 */ - out_le32(mbase + PCI_BASE_ADDRESS_0, 0); - out_le32(mbase + PCI_BASE_ADDRESS_1, 0); - - out_le32(mbase + PECFG_PIM01SAH, 0xffffffff); - out_le32(mbase + PECFG_PIM01SAL, 0xfc000000); - - /* Setup BAR0 */ - out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffff); - out_le32(mbase + PECFG_BAR0LMPA, 0xfc000000 | PCI_BASE_ADDRESS_MEM_TYPE_64); - - /* Disable BAR1 & BAR2 */ - out_le32(mbase + PECFG_BAR1MPA, 0); - out_le32(mbase + PECFG_BAR2HMPA, 0); - out_le32(mbase + PECFG_BAR2LMPA, 0); - - out_le32(mbase + PECFG_PIM0LAL, U64_TO_U32_LOW(CONFIG_SYS_PCIE_INBOUND_BASE)); - out_le32(mbase + PECFG_PIM0LAH, U64_TO_U32_HIGH(CONFIG_SYS_PCIE_INBOUND_BASE)); - out_le32(mbase + PECFG_PIMEN, 0x1); - - /* Enable I/O, Mem, and Busmaster cycles */ - out_le16((u16 *)(mbase + PCI_COMMAND), - in_le16((u16 *)(mbase + PCI_COMMAND)) | - PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - out_le16(mbase + 0x200, 0xcaad); /* Setting vendor ID */ - out_le16(mbase + 0x202, 0xfeed); /* Setting device ID */ - - /* Set Class Code to Processor/PPC */ - out_le32(mbase + 0x208, 0x0b200001); - - attempts = 10; - while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 8))) { - if (!(attempts--)) { - printf("PCIE%d: BME not active\n", port); - return -1; - } - mdelay(1000); - } - - printf("PCIE%d: successfully set as endpoint\n", port); - - return 0; -} -#endif /* CONFIG_440SPE && CONFIG_PCI */ diff --git a/arch/powerpc/cpu/ppc4xx/4xx_uart.c b/arch/powerpc/cpu/ppc4xx/4xx_uart.c deleted file mode 100644 index 2660aa8..0000000 --- a/arch/powerpc/cpu/ppc4xx/4xx_uart.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * (C) Copyright 2000-2006 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2010 - * Stefan Roese, DENX Software Engineering, sr@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 - */ - -/* - * 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 - */ - -#include <common.h> -#include <commproc.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <watchdog.h> -#include <asm/ppc4xx.h> - -DECLARE_GLOBAL_DATA_PTR; - -#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ - defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_405EX) || defined(CONFIG_440) - -#if defined(CONFIG_440) - -#if defined(CONFIG_440GP) -#define CR0_MASK 0x3fff0000 -#define CR0_EXTCLK_ENA 0x00600000 -#define CR0_UDIV_POS 16 -#define UDIV_SUBTRACT 1 -#define UART0_SDR CPC0_CR0 -#define MFREG(a, d) d = mfdcr(a) -#define MTREG(a, d) mtdcr(a, d) -#else /* #if defined(CONFIG_440GP) */ -/* all other 440 PPC's access clock divider via sdr register */ -#define CR0_MASK 0xdfffffff -#define CR0_EXTCLK_ENA 0x00800000 -#define CR0_UDIV_POS 0 -#define UDIV_SUBTRACT 0 -#define UART0_SDR SDR0_UART0 -#define UART1_SDR SDR0_UART1 -#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) -#define UART2_SDR SDR0_UART2 -#endif -#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) -#define UART3_SDR SDR0_UART3 -#endif -#define MFREG(a, d) mfsdr(a, d) -#define MTREG(a, d) mtsdr(a, d) -#endif /* #if defined(CONFIG_440GP) */ -#elif defined(CONFIG_405EP) || defined(CONFIG_405EZ) -#define UCR0_MASK 0x0000007f -#define UCR1_MASK 0x00007f00 -#define UCR0_UDIV_POS 0 -#define UCR1_UDIV_POS 8 -#define UDIV_MAX 127 -#elif defined(CONFIG_405EX) -#define MFREG(a, d) mfsdr(a, d) -#define MTREG(a, d) mtsdr(a, d) -#define CR0_MASK 0x000000ff -#define CR0_EXTCLK_ENA 0x00800000 -#define CR0_UDIV_POS 0 -#define UDIV_SUBTRACT 0 -#define UART0_SDR SDR0_UART0 -#define UART1_SDR SDR0_UART1 -#else /* CONFIG_405GP || CONFIG_405CR */ -#define CR0_MASK 0x00001fff -#define CR0_EXTCLK_ENA 0x000000c0 -#define CR0_UDIV_POS 1 -#define UDIV_MAX 32 -#endif - -#if defined(CONFIG_405EP) && defined(CONFIG_SYS_EXT_SERIAL_CLOCK) -#error "External serial clock not supported on AMCC PPC405EP!" -#endif - -#if (defined(CONFIG_405EX) || defined(CONFIG_405EZ) || \ - defined(CONFIG_440)) && !defined(CONFIG_SYS_EXT_SERIAL_CLOCK) -/* - * For some SoC's, the cpu clock is on divider chain A, UART on - * divider chain B ... so cpu clock is irrelevant. Get the - * "optimized" values that are subject to the 1/2 opb clock - * constraint. - */ -static u16 serial_bdiv(int baudrate, u32 *udiv) -{ - sys_info_t sysinfo; - u32 div; /* total divisor udiv * bdiv */ - u32 umin; /* minimum udiv */ - u16 diff; /* smallest diff */ - u16 idiff; /* current diff */ - u16 ibdiv; /* current bdiv */ - u32 i; - u32 est; /* current estimate */ - u32 max; -#if defined(CONFIG_405EZ) - u32 cpr_pllc; - u32 plloutb; - u32 reg; -#endif - - get_sys_info(&sysinfo); - -#if defined(CONFIG_405EZ) - /* check the pll feedback source */ - mfcpr(CPR0_PLLC, cpr_pllc); - plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ? - sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) * - sysinfo.pllFbkDiv) / sysinfo.pllFwdDivB); - div = plloutb / (16 * baudrate); /* total divisor */ - umin = (plloutb / get_OPB_freq()) << 1; /* 2 x OPB divisor */ - max = 256; /* highest possible */ -#else /* 405EZ */ - div = sysinfo.freqPLB / (16 * baudrate); /* total divisor */ - umin = sysinfo.pllOpbDiv << 1; /* 2 x OPB divisor */ - max = 32; /* highest possible */ -#endif /* 405EZ */ - - *udiv = diff = max; - - /* - * i is the test udiv value -- start with the largest - * possible (max) to minimize serial clock and constrain - * search to umin. - */ - for (i = max; i > umin; i--) { - ibdiv = div / i; - est = i * ibdiv; - idiff = (est > div) ? (est - div) : (div - est); - if (idiff == 0) { - *udiv = i; - break; /* can't do better */ - } else if (idiff < diff) { - *udiv = i; /* best so far */ - diff = idiff; /* update lowest diff*/ - } - } - -#if defined(CONFIG_405EZ) - mfcpr(CPR0_PERD0, reg); - reg &= ~0x0000ffff; - reg |= ((*udiv - 0) << 8) | (*udiv - 0); - mtcpr(CPR0_PERD0, reg); -#endif - - return div / *udiv; -} -#endif /* #if (defined(CONFIG_405EP) ... */ - -/* - * This function returns the UART clock used by the common - * NS16550 driver. Additionally the SoC internal divisors for - * optimal UART baudrate are configured. - */ -int get_serial_clock(void) -{ - u32 clk; - u32 udiv; -#if defined(CONFIG_405CR) || defined(CONFIG_405EP) || defined(CONFIG_405GP) - u32 tmp; -#endif -#if !defined(CONFIG_405EZ) - u32 reg; -#endif -#if !defined(CONFIG_SYS_EXT_SERIAL_CLOCK) - PPC4xx_SYS_INFO sys_info; -#endif - - /* - * Programming of the internal divisors is SoC specific. - * Let's handle this in some #ifdef's for the SoC's. - */ - -#if defined(CONFIG_405CR) || defined(CONFIG_405GP) - tmp = 0; - reg = mfdcr(CPC0_CR0) & ~CR0_MASK; -#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK - clk = CONFIG_SYS_EXT_SERIAL_CLOCK; - udiv = 1; - reg |= CR0_EXTCLK_ENA; -#else /* CONFIG_SYS_EXT_SERIAL_CLOCK */ - clk = gd->cpu_clk; -#ifdef CONFIG_SYS_405_UART_ERRATA_59 - udiv = 31; /* Errata 59: stuck at 31 */ -#else /* CONFIG_SYS_405_UART_ERRATA_59 */ - tmp = CONFIG_SYS_BASE_BAUD * 16; - udiv = (clk + tmp / 2) / tmp; - if (udiv > UDIV_MAX) /* max. n bits for udiv */ - udiv = UDIV_MAX; -#endif /* CONFIG_SYS_405_UART_ERRATA_59 */ -#endif /* CONFIG_SYS_EXT_SERIAL_CLOCK */ - reg |= (udiv - 1) << CR0_UDIV_POS; /* set the UART divisor */ - mtdcr (CPC0_CR0, reg); -#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK - clk = CONFIG_SYS_EXT_SERIAL_CLOCK; -#else - clk = CONFIG_SYS_BASE_BAUD * 16; -#endif -#endif /* CONFIG_405CR */ - -#if defined(CONFIG_405EP) - reg = mfdcr(CPC0_UCR) & ~(UCR0_MASK | UCR1_MASK); - clk = gd->cpu_clk; - tmp = CONFIG_SYS_BASE_BAUD * 16; - udiv = (clk + tmp / 2) / tmp; - if (udiv > UDIV_MAX) /* max. n bits for udiv */ - udiv = UDIV_MAX; - reg |= udiv << UCR0_UDIV_POS; /* set the UART divisor */ - reg |= udiv << UCR1_UDIV_POS; /* set the UART divisor */ - mtdcr(CPC0_UCR, reg); - clk = CONFIG_SYS_BASE_BAUD * 16; -#endif /* CONFIG_405EP */ - -#if defined(CONFIG_405EX) || defined(CONFIG_440) - MFREG(UART0_SDR, reg); - reg &= ~CR0_MASK; - -#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK - reg |= CR0_EXTCLK_ENA; - udiv = 1; - clk = CONFIG_SYS_EXT_SERIAL_CLOCK; -#else /* CONFIG_SYS_EXT_SERIAL_CLOCK */ - clk = gd->baudrate * serial_bdiv(gd->baudrate, &udiv) * 16; -#endif /* CONFIG_SYS_EXT_SERIAL_CLOCK */ - - reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS; /* set the UART divisor */ - - /* - * Configure input clock to baudrate generator for all - * available serial ports here - */ - MTREG(UART0_SDR, reg); -#if defined(UART1_SDR) - MTREG(UART1_SDR, reg); -#endif -#if defined(UART2_SDR) - MTREG(UART2_SDR, reg); -#endif -#if defined(UART3_SDR) - MTREG(UART3_SDR, reg); -#endif -#endif /* CONFIG_405EX ... */ - -#if defined(CONFIG_405EZ) - clk = gd->baudrate * serial_bdiv(gd->baudrate, &udiv) * 16; -#endif /* CONFIG_405EZ */ - - /* - * Correct UART frequency in bd-info struct now that - * the UART divisor is available - */ -#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK - gd->uart_clk = CONFIG_SYS_EXT_SERIAL_CLOCK; -#else - get_sys_info(&sys_info); - gd->uart_clk = sys_info.freqUART / udiv; -#endif - - return clk; -} -#endif /* CONFIG_405GP || CONFIG_405CR */ diff --git a/arch/powerpc/cpu/ppc4xx/Makefile b/arch/powerpc/cpu/ppc4xx/Makefile deleted file mode 100644 index d97ca20..0000000 --- a/arch/powerpc/cpu/ppc4xx/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -# -# (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 - -LIB = $(obj)lib$(CPU).o - -START := resetvec.o -START += start.o - -SOBJS := cache.o -SOBJS += dcr.o -SOBJS += kgdb.o - -COBJS := 40x_spd_sdram.o - -ifndef CONFIG_NAND_SPL -ifndef CONFIG_NAND_U_BOOT -COBJS += 44x_spd_ddr.o -endif -endif -COBJS-$(CONFIG_SDRAM_PPC4xx_IBM_DDR2) += 44x_spd_ddr2.o -COBJS-$(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) += 4xx_ibm_ddr2_autocalib.o -COBJS += 4xx_pci.o -COBJS += 4xx_pcie.o -COBJS += bedbug_405.o -COBJS-$(CONFIG_CMD_CHIP_CONFIG) += cmd_chip_config.o -COBJS += cpu.o -COBJS += cpu_init.o -COBJS += denali_data_eye.o -COBJS += denali_spd_ddr2.o -COBJS += ecc.o -COBJS-$(CONFIG_CMD_ECCTEST) += cmd_ecctest.o -COBJS += fdt.o -COBJS += interrupts.o -COBJS += iop480_uart.o -COBJS-$(CONFIG_CMD_REGINFO) += reginfo.o -COBJS += sdram.o -COBJS += speed.o -COBJS += tlb.o -COBJS += traps.o -COBJS += usb.o -COBJS += usb_ohci.o -COBJS += usbdev.o -COBJS-$(CONFIG_XILINX_440) += xilinx_irq.o -ifndef CONFIG_XILINX_440 -COBJS += 4xx_uart.o -COBJS += gpio.o -COBJS += miiphy.o -COBJS += uic.o -endif - -SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS) $(COBJS-y)) -START := $(addprefix $(obj),$(START)) - -all: $(obj).depend $(START) $(LIB) - -$(LIB): $(OBJS) - $(call cmd_link_o_target, $(OBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/arch/powerpc/cpu/ppc4xx/bedbug_405.c b/arch/powerpc/cpu/ppc4xx/bedbug_405.c deleted file mode 100644 index e1500cc..0000000 --- a/arch/powerpc/cpu/ppc4xx/bedbug_405.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Bedbug Functions specific to the PPC405 chip - */ - -#include <common.h> -#include <command.h> -#include <linux/ctype.h> -#include <bedbug/type.h> -#include <bedbug/bedbug.h> -#include <bedbug/regs.h> -#include <bedbug/ppc.h> - -#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_4xx) - -#define MAX_BREAK_POINTS 4 - -extern CPU_DEBUG_CTX bug_ctx; - -void bedbug405_init __P ((void)); -void bedbug405_do_break __P ((cmd_tbl_t *, int, int, char * const [])); -void bedbug405_break_isr __P ((struct pt_regs *)); -int bedbug405_find_empty __P ((void)); -int bedbug405_set __P ((int, unsigned long)); -int bedbug405_clear __P ((int)); - - -/* ====================================================================== - * Initialize the global bug_ctx structure for the AMCC PPC405. Clear all - * of the breakpoints. - * ====================================================================== */ - -void bedbug405_init (void) -{ - int i; - - /* -------------------------------------------------- */ - - bug_ctx.hw_debug_enabled = 0; - bug_ctx.stopped = 0; - bug_ctx.current_bp = 0; - bug_ctx.regs = NULL; - - bug_ctx.do_break = bedbug405_do_break; - bug_ctx.break_isr = bedbug405_break_isr; - bug_ctx.find_empty = bedbug405_find_empty; - bug_ctx.set = bedbug405_set; - bug_ctx.clear = bedbug405_clear; - - for (i = 1; i <= MAX_BREAK_POINTS; ++i) - (*bug_ctx.clear) (i); - - puts ("BEDBUG:ready\n"); - return; -} /* bedbug_init_breakpoints */ - - - -/* ====================================================================== - * Set/clear/show one of the hardware breakpoints for the 405. The "off" - * string will disable a specific breakpoint. The "show" string will - * display the current breakpoints. Otherwise an address will set a - * breakpoint at that address. Setting a breakpoint uses the CPU-specific - * set routine which will assign a breakpoint number. - * ====================================================================== */ - -void bedbug405_do_break (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - long addr = 0; /* Address to break at */ - int which_bp; /* Breakpoint number */ - - /* -------------------------------------------------- */ - - if (argc < 2) { - cmd_usage(cmdtp); - return; - } - - /* Turn off a breakpoint */ - - if (strcmp (argv[1], "off") == 0) { - if (bug_ctx.hw_debug_enabled == 0) { - printf ("No breakpoints enabled\n"); - return; - } - - which_bp = simple_strtoul (argv[2], NULL, 10); - - if (bug_ctx.clear) - (*bug_ctx.clear) (which_bp); - - printf ("Breakpoint %d removed\n", which_bp); - return; - } - - /* Show a list of breakpoints */ - - if (strcmp (argv[1], "show") == 0) { - for (which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp) { - - switch (which_bp) { - case 1: - addr = GET_IAC1 (); - break; - case 2: - addr = GET_IAC2 (); - break; - case 3: - addr = GET_IAC3 (); - break; - case 4: - addr = GET_IAC4 (); - break; - } - - printf ("Breakpoint [%d]: ", which_bp); - if (addr == 0) - printf ("NOT SET\n"); - else - disppc ((unsigned char *) addr, 0, 1, bedbug_puts, - F_RADHEX); - } - return; - } - - /* Set a breakpoint at the address */ - - if (!isdigit (argv[1][0])) { - cmd_usage(cmdtp); - return; - } - - addr = simple_strtoul (argv[1], NULL, 16) & 0xfffffffc; - - if ((bug_ctx.set) && (which_bp = (*bug_ctx.set) (0, addr)) > 0) { - printf ("Breakpoint [%d]: ", which_bp); - disppc ((unsigned char *) addr, 0, 1, bedbug_puts, F_RADHEX); - } - - return; -} /* bedbug405_do_break */ - - - -/* ====================================================================== - * Handle a breakpoint. First determine which breakpoint was hit by - * looking at the DeBug Status Register (DBSR), clear the breakpoint - * and enter a mini main loop. Stay in the loop until the stopped flag - * in the debug context is cleared. - * ====================================================================== */ - -void bedbug405_break_isr (struct pt_regs *regs) -{ - unsigned long dbsr_val; /* Value of the DBSR */ - unsigned long addr = 0; /* Address stopped at */ - - /* -------------------------------------------------- */ - - dbsr_val = GET_DBSR (); - - if (dbsr_val & DBSR_IA1) { - bug_ctx.current_bp = 1; - addr = GET_IAC1 (); - SET_DBSR (DBSR_IA1); /* Write a 1 to clear */ - } else if (dbsr_val & DBSR_IA2) { - bug_ctx.current_bp = 2; - addr = GET_IAC2 (); - SET_DBSR (DBSR_IA2); /* Write a 1 to clear */ - } else if (dbsr_val & DBSR_IA3) { - bug_ctx.current_bp = 3; - addr = GET_IAC3 (); - SET_DBSR (DBSR_IA3); /* Write a 1 to clear */ - } else if (dbsr_val & DBSR_IA4) { - bug_ctx.current_bp = 4; - addr = GET_IAC4 (); - SET_DBSR (DBSR_IA4); /* Write a 1 to clear */ - } - - bedbug_main_loop (addr, regs); - return; -} /* bedbug405_break_isr */ - - - -/* ====================================================================== - * Look through all of the hardware breakpoints available to see if one - * is unused. - * ====================================================================== */ - -int bedbug405_find_empty (void) -{ - /* -------------------------------------------------- */ - - if (GET_IAC1 () == 0) - return 1; - - if (GET_IAC2 () == 0) - return 2; - - if (GET_IAC3 () == 0) - return 3; - - if (GET_IAC4 () == 0) - return 4; - - return 0; -} /* bedbug405_find_empty */ - - - -/* ====================================================================== - * Set a breakpoint. If 'which_bp' is zero then find an unused breakpoint - * number, otherwise reassign the given breakpoint. If hardware debugging - * is not enabled, then turn it on via the MSR and DBCR0. Set the break - * address in the appropriate IACx register and enable proper address - * beakpoint in DBCR0. - * ====================================================================== */ - -int bedbug405_set (int which_bp, unsigned long addr) -{ - /* -------------------------------------------------- */ - - /* Only look if which_bp == 0, else use which_bp */ - if ((bug_ctx.find_empty) && (!which_bp) && - (which_bp = (*bug_ctx.find_empty) ()) == 0) { - printf ("All breakpoints in use\n"); - return 0; - } - - if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) { - printf ("Invalid break point # %d\n", which_bp); - return 0; - } - - if (!bug_ctx.hw_debug_enabled) { - SET_MSR (GET_MSR () | 0x200); /* set MSR[ DE ] */ - SET_DBCR0 (GET_DBCR0 () | DBCR0_IDM); - bug_ctx.hw_debug_enabled = 1; - } - - switch (which_bp) { - case 1: - SET_IAC1 (addr); - SET_DBCR0 (GET_DBCR0 () | DBCR0_IA1); - break; - - case 2: - SET_IAC2 (addr); - SET_DBCR0 (GET_DBCR0 () | DBCR0_IA2); - break; - - case 3: - SET_IAC3 (addr); - SET_DBCR0 (GET_DBCR0 () | DBCR0_IA3); - break; - - case 4: - SET_IAC4 (addr); - SET_DBCR0 (GET_DBCR0 () | DBCR0_IA4); - break; - } - - return which_bp; -} /* bedbug405_set */ - - - -/* ====================================================================== - * Disable a specific breakoint by setting the appropriate IACx register - * to zero and claring the instruction address breakpoint in DBCR0. - * ====================================================================== */ - -int bedbug405_clear (int which_bp) -{ - /* -------------------------------------------------- */ - - if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) { - printf ("Invalid break point # (%d)\n", which_bp); - return -1; - } - - switch (which_bp) { - case 1: - SET_IAC1 (0); - SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA1); - break; - - case 2: - SET_IAC2 (0); - SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA2); - break; - - case 3: - SET_IAC3 (0); - SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA3); - break; - - case 4: - SET_IAC4 (0); - SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA4); - break; - } - - return 0; -} /* bedbug405_clear */ - - -/* ====================================================================== */ -#endif diff --git a/arch/powerpc/cpu/ppc4xx/cache.S b/arch/powerpc/cpu/ppc4xx/cache.S deleted file mode 100644 index 757d7da..0000000 --- a/arch/powerpc/cpu/ppc4xx/cache.S +++ /dev/null @@ -1,235 +0,0 @@ -/* - * This file contains miscellaneous low-level functions. - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * - * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) - * and Paul Mackerras. - * - * 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. - * - */ - -#include <config.h> -#include <config.h> -#include <asm/ppc4xx.h> -#include <ppc_asm.tmpl> -#include <ppc_defs.h> -#include <asm/cache.h> -#include <asm/mmu.h> - -/* - * Flush instruction cache. - */ -_GLOBAL(invalidate_icache) - iccci r0,r0 - isync - blr - -/* - * Write any modified data cache blocks out to memory - * and invalidate the corresponding instruction cache blocks. - * - * flush_icache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(flush_icache_range) - li r5,L1_CACHE_BYTES-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,L1_CACHE_SHIFT - beqlr - mtctr r4 - mr r6,r3 -1: dcbst 0,r3 - addi r3,r3,L1_CACHE_BYTES - bdnz 1b - sync /* wait for dcbst's to get to ram */ - mtctr r4 -2: icbi 0,r6 - addi r6,r6,L1_CACHE_BYTES - bdnz 2b - sync /* additional sync needed on g4 */ - isync - blr - -/* - * Write any modified data cache blocks out to memory. - * Does not invalidate the corresponding cache lines (especially for - * any corresponding instruction cache). - * - * clean_dcache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(clean_dcache_range) - li r5,L1_CACHE_BYTES-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,L1_CACHE_SHIFT - beqlr - mtctr r4 - -1: dcbst 0,r3 - addi r3,r3,L1_CACHE_BYTES - bdnz 1b - sync /* wait for dcbst's to get to ram */ - blr - -/* - * Write any modified data cache blocks out to memory and invalidate them. - * Does not invalidate the corresponding instruction cache blocks. - * - * flush_dcache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(flush_dcache_range) - li r5,L1_CACHE_BYTES-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,L1_CACHE_SHIFT - beqlr - mtctr r4 - -1: dcbf 0,r3 - addi r3,r3,L1_CACHE_BYTES - bdnz 1b - sync /* wait for dcbst's to get to ram */ - blr - -/* - * Like above, but invalidate the D-cache. This is used by the 8xx - * to invalidate the cache so the PPC core doesn't get stale data - * from the CPM (no cache snooping here :-). - * - * invalidate_dcache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(invalidate_dcache_range) - li r5,L1_CACHE_BYTES-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,L1_CACHE_SHIFT - beqlr - mtctr r4 - -1: dcbi 0,r3 - addi r3,r3,L1_CACHE_BYTES - bdnz 1b - sync /* wait for dcbi's to get to ram */ - blr - -/* - * 40x cores have 8K or 16K dcache and 32 byte line size. - * 44x has a 32K dcache and 32 byte line size. - * 8xx has 1, 2, 4, 8K variants. - * For now, cover the worst case of the 44x. - * Must be called with external interrupts disabled. - */ -#define CACHE_NWAYS 64 -#define CACHE_NLINES 32 - -_GLOBAL(flush_dcache) - li r4,(2 * CACHE_NWAYS * CACHE_NLINES) - mtctr r4 - lis r5,0 -1: lwz r3,0(r5) /* Load one word from every line */ - addi r5,r5,L1_CACHE_BYTES - bdnz 1b - sync - blr - -_GLOBAL(invalidate_dcache) - addi r6,0,0x0000 /* clear GPR 6 */ - /* Do loop for # of dcache congruence classes. */ - lis r7,(CONFIG_SYS_DCACHE_SIZE / L1_CACHE_BYTES / 2)@ha /* TBS for large sized cache */ - ori r7,r7,(CONFIG_SYS_DCACHE_SIZE / L1_CACHE_BYTES / 2)@l - /* NOTE: dccci invalidates both */ - mtctr r7 /* ways in the D cache */ -..dcloop: - dccci 0,r6 /* invalidate line */ - addi r6,r6,L1_CACHE_BYTES /* bump to next line */ - bdnz ..dcloop - sync - blr - -/* - * Cache functions. - * - * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM, - * although for some cache-ralated calls stubs have to be provided to satisfy - * symbols resolution. - * Icache-related functions are used in POST framework. - * - */ -#ifdef CONFIG_440 - - .globl dcache_disable - .globl dcache_enable - .globl icache_disable - .globl icache_enable -dcache_disable: -dcache_enable: -icache_disable: -icache_enable: - blr - - .globl dcache_status - .globl icache_status -dcache_status: -icache_status: - mr r3, 0 - blr - -#else /* CONFIG_440 */ - - .globl icache_enable -icache_enable: - mflr r8 - bl invalidate_icache - mtlr r8 - isync - addis r3,r0, 0xc000 /* set bit 0 */ - mticcr r3 - blr - - .globl icache_disable -icache_disable: - addis r3,r0, 0x0000 /* clear bit 0 */ - mticcr r3 - isync - blr - - .globl icache_status -icache_status: - mficcr r3 - srwi r3, r3, 31 /* >>31 => select bit 0 */ - blr - - .globl dcache_enable -dcache_enable: - mflr r8 - bl invalidate_dcache - mtlr r8 - isync - addis r3,r0, 0x8000 /* set bit 0 */ - mtdccr r3 - blr - - .globl dcache_disable -dcache_disable: - mflr r8 - bl flush_dcache - mtlr r8 - addis r3,r0, 0x0000 /* clear bit 0 */ - mtdccr r3 - blr - - .globl dcache_status -dcache_status: - mfdccr r3 - srwi r3, r3, 31 /* >>31 => select bit 0 */ - blr - -#endif /* CONFIG_440 */ diff --git a/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c b/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c deleted file mode 100644 index 72c5aec..0000000 --- a/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * (C) Copyright 2008-2009 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * (C) Copyright 2009 - * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#include <common.h> -#include <command.h> -#include <i2c.h> -#include <asm/ppc4xx_config.h> -#include <asm/io.h> - -static void print_configs(int cur_config_nr) -{ - int i; - - for (i = 0; i < ppc4xx_config_count; i++) { - printf("%-16s - %s", ppc4xx_config_val[i].label, - ppc4xx_config_val[i].description); - if (i == cur_config_nr) - printf(" ***"); - printf("\n"); - } - -} - -static int do_chip_config(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i; - int ret; - int cur_config_nr = -1; - u8 cur_config[CONFIG_4xx_CONFIG_BLOCKSIZE]; - - /* - * First switch to correct I2C bus. This is I2C bus 0 - * for all currently available 4xx derivats. - */ - I2C_SET_BUS(0); - -#ifdef CONFIG_CMD_EEPROM - ret = eeprom_read(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR, - CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET, - cur_config, CONFIG_4xx_CONFIG_BLOCKSIZE); -#else - ret = i2c_read(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR, - CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET, - 1, cur_config, CONFIG_4xx_CONFIG_BLOCKSIZE); -#endif - if (ret) { - printf("Error reading EEPROM at addr 0x%x\n", - CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR); - return -1; - } - - /* - * Search the current configuration - */ - for (i = 0; i < ppc4xx_config_count; i++) { - if (memcmp(cur_config, ppc4xx_config_val[i].val, - CONFIG_4xx_CONFIG_BLOCKSIZE) == 0) - cur_config_nr = i; - } - - if (cur_config_nr == -1) { - printf("Warning: The I2C bootstrap values don't match any" - " of the available options!\n"); - printf("I2C bootstrap EEPROM values are (I2C address 0x%02x):\n", - CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR); - for (i = 0; i < CONFIG_4xx_CONFIG_BLOCKSIZE; i++) { - printf("%02x ", cur_config[i]); - } - printf("\n"); - } - - if (argc < 2) { - printf("Available configurations (I2C address 0x%02x):\n", - CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR); - print_configs(cur_config_nr); - return 0; - } - - for (i = 0; i < ppc4xx_config_count; i++) { - /* - * Search for configuration name/label - */ - if (strcmp(argv[1], ppc4xx_config_val[i].label) == 0) { - printf("Using configuration:\n%-16s - %s\n", - ppc4xx_config_val[i].label, - ppc4xx_config_val[i].description); - -#ifdef CONFIG_CMD_EEPROM - ret = eeprom_write(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR, - CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET, - ppc4xx_config_val[i].val, - CONFIG_4xx_CONFIG_BLOCKSIZE); -#else - ret = i2c_write(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR, - CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET, - 1, ppc4xx_config_val[i].val, - CONFIG_4xx_CONFIG_BLOCKSIZE); -#endif - udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000); - if (ret) { - printf("Error updating EEPROM at addr 0x%x\n", - CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR); - return -1; - } - - printf("done (dump via 'i2c md %x 0.1 %x')\n", - CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR, - CONFIG_4xx_CONFIG_BLOCKSIZE); - printf("Reset the board for the changes to" - " take effect\n"); - return 0; - } - } - - printf("Configuration %s not found!\n", argv[1]); - print_configs(cur_config_nr); - return -1; -} - -U_BOOT_CMD( - chip_config, 2, 0, do_chip_config, - "program the I2C bootstrap EEPROM", - "[config-label]" -); diff --git a/arch/powerpc/cpu/ppc4xx/cmd_ecctest.c b/arch/powerpc/cpu/ppc4xx/cmd_ecctest.c deleted file mode 100644 index 542ab69..0000000 --- a/arch/powerpc/cpu/ppc4xx/cmd_ecctest.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * (C) Copyright 2010 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#include <common.h> -#include <asm/ppc4xx.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <asm/cache.h> - -#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \ - defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) -#if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) - -#if defined(CONFIG_405EX) -/* - * Currently only 405EX uses 16bit data bus width as an alternative - * option to 32bit data width (SDRAM0_MCOPT1_WDTH) - */ -#define SDRAM_DATA_ALT_WIDTH 2 -#else -#define SDRAM_DATA_ALT_WIDTH 8 -#endif - -#if defined(CONFIG_SYS_OCM_BASE) -#define CONFIG_FUNC_ISRAM_ADDR CONFIG_SYS_OCM_BASE -#endif - -#if defined(CONFIG_SYS_ISRAM_BASE) -#define CONFIG_FUNC_ISRAM_ADDR CONFIG_SYS_ISRAM_BASE -#endif - -#if !defined(CONFIG_FUNC_ISRAM_ADDR) -#error "No internal SRAM/OCM provided!" -#endif - -#define force_inline inline __attribute__ ((always_inline)) - -static inline void machine_check_disable(void) -{ - mtmsr(mfmsr() & ~MSR_ME); -} - -static inline void machine_check_enable(void) -{ - mtmsr(mfmsr() | MSR_ME); -} - -/* - * These helper functions need to be inlined, since they - * are called from the functions running from internal SRAM. - * SDRAM operation is forbidden at that time, so calling - * functions in SDRAM has to be avoided. - */ -static force_inline void wait_ddr_idle(void) -{ - u32 val; - - do { - mfsdram(SDRAM_MCSTAT, val); - } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT); -} - -static force_inline void recalibrate_ddr(void) -{ - u32 val; - - /* - * Rewrite RQDC & RFDC to calibrate again. If this is not - * done, the SDRAM controller is working correctly after - * changing the MCOPT1_MCHK bits. - */ - mfsdram(SDRAM_RQDC, val); - mtsdram(SDRAM_RQDC, val); - mfsdram(SDRAM_RFDC, val); - mtsdram(SDRAM_RFDC, val); -} - -static force_inline void set_mcopt1_mchk(u32 bits) -{ - u32 val; - - wait_ddr_idle(); - mfsdram(SDRAM_MCOPT1, val); - mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) | bits); - recalibrate_ddr(); -} - -/* - * The next 2 functions are copied to internal SRAM/OCM and run - * there. No function calls allowed here. No SDRAM acitivity should - * be done here. - */ -static void inject_ecc_error(void *ptr, int par) -{ - u32 val; - - /* - * Taken from PPC460EX/EXr/GT users manual (Rev 1.21) - * 22.2.17.13 ECC Diagnostics - * - * Items 1 ... 5 are already done by now, running from RAM - * with ECC enabled - */ - - out_be32(ptr, 0x00000000); - val = in_be32(ptr); - - /* 6. Set memory controller to no error checking */ - set_mcopt1_mchk(SDRAM_MCOPT1_MCHK_NON); - - /* 7. Modify one or two bits for error simulation */ - if (par == 1) - out_be32(ptr, in_be32(ptr) ^ 0x00000001); - else - out_be32(ptr, in_be32(ptr) ^ 0x00000003); - - /* 8. Wait for SDRAM idle */ - val = in_be32(ptr); - set_mcopt1_mchk(SDRAM_MCOPT1_MCHK_CHK_REP); - - /* Wait for SDRAM idle */ - wait_ddr_idle(); - - /* Continue with 9. in calling function... */ -} - -static void rewrite_ecc_parity(void *ptr, int par) -{ - u32 current_address = (u32)ptr; - u32 end_address; - u32 address_increment; - u32 mcopt1; - u32 val; - - /* - * Fill ECC parity byte again. Otherwise further accesses to - * the failure address will result in exceptions. - */ - - /* Wait for SDRAM idle */ - val = in_be32(0x00000000); - set_mcopt1_mchk(SDRAM_MCOPT1_MCHK_GEN); - - /* ECC bit set method for non-cached memory */ - mfsdram(SDRAM_MCOPT1, mcopt1); - if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32) - address_increment = 4; - else - address_increment = SDRAM_DATA_ALT_WIDTH; - end_address = current_address + CONFIG_SYS_CACHELINE_SIZE; - - while (current_address < end_address) { - *((unsigned long *)current_address) = 0; - current_address += address_increment; - } - - set_mcopt1_mchk(SDRAM_MCOPT1_MCHK_CHK_REP); - - /* Wait for SDRAM idle */ - wait_ddr_idle(); -} - -static int do_ecctest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - u32 old_val; - u32 val; - u32 *ptr; - void (*sram_func)(u32 *, int); - int error; - - if (argc < 3) { - return cmd_usage(cmdtp); - } - - ptr = (u32 *)simple_strtoul(argv[1], NULL, 16); - error = simple_strtoul(argv[2], NULL, 16); - if ((error < 1) || (error > 2)) { - return cmd_usage(cmdtp); - } - - printf("Using address %p for %d bit ECC error injection\n", - ptr, error); - - /* - * Save value to restore it later on - */ - old_val = in_be32(ptr); - - /* - * Copy ECC injection function into internal SRAM/OCM - */ - sram_func = (void *)CONFIG_FUNC_ISRAM_ADDR; - memcpy((void *)CONFIG_FUNC_ISRAM_ADDR, inject_ecc_error, 0x10000); - - /* - * Disable interrupts and exceptions before calling this - * function in internal SRAM/OCM - */ - disable_interrupts(); - machine_check_disable(); - eieio(); - - /* - * Jump to ECC simulation function in internal SRAM/OCM - */ - (*sram_func)(ptr, error); - - /* 10. Read the corresponding address */ - val = in_be32(ptr); - - /* - * Read and print ECC status register/info: - * The faulting address is only known upon uncorrectable ECC - * errors. - */ - mfsdram(SDRAM_ECCES, val); - if (val & SDRAM_ECCES_CE) - printf("ECC: Correctable error\n"); - if (val & SDRAM_ECCES_UE) { - printf("ECC: Uncorrectable error at 0x%02x%08x\n", - mfdcr(SDRAM_ERRADDULL), mfdcr(SDRAM_ERRADDLLL)); - } - - /* - * Clear pending interrupts/exceptions - */ - mtsdram(SDRAM_ECCES, 0xffffffff); - mtdcr(SDRAM_ERRSTATLL, 0xff000000); - set_mcsr(get_mcsr()); - - /* Now enable interrupts and exceptions again */ - eieio(); - machine_check_enable(); - enable_interrupts(); - - /* - * The ECC parity byte need to be re-written for the - * corresponding address. Otherwise future accesses to it - * will result in exceptions. - * - * Jump to ECC parity generation function - */ - memcpy((void *)CONFIG_FUNC_ISRAM_ADDR, rewrite_ecc_parity, 0x10000); - (*sram_func)(ptr, 0); - - /* - * Restore value in corresponding address - */ - out_be32(ptr, old_val); - - return 0; -} - -U_BOOT_CMD( - ecctest, 3, 0, do_ecctest, - "Test ECC by single and double error bit injection", - "address 1/2" -); - -#endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */ -#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */ diff --git a/arch/powerpc/cpu/ppc4xx/config.mk b/arch/powerpc/cpu/ppc4xx/config.mk deleted file mode 100644 index d862bb4..0000000 --- a/arch/powerpc/cpu/ppc4xx/config.mk +++ /dev/null @@ -1,34 +0,0 @@ -# -# (C) Copyright 2000-2010 -# 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 -# - -PLATFORM_RELFLAGS += -fPIC -meabi -PLATFORM_CPPFLAGS += -DCONFIG_4xx -ffixed-r2 -mstring -msoft-float - -cfg=$(shell grep configs $(OBJTREE)/include/config.h | sed 's/.*<\(configs.*\)>/\1/') -is440:=$(shell grep CONFIG_440 $(TOPDIR)/include/$(cfg)) - -ifneq (,$(findstring CONFIG_440,$(is440))) -PLATFORM_CPPFLAGS += -Wa,-m440 -mcpu=440 -else -PLATFORM_CPPFLAGS += -Wa,-m405 -mcpu=405 -endif diff --git a/arch/powerpc/cpu/ppc4xx/cpu.c b/arch/powerpc/cpu/ppc4xx/cpu.c deleted file mode 100644 index 67f1fff..0000000 --- a/arch/powerpc/cpu/ppc4xx/cpu.c +++ /dev/null @@ -1,765 +0,0 @@ -/* - * (C) Copyright 2000-2007 - * 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 - */ - -/* - * CPU specific code - * - * written or collected and sometimes rewritten by - * Magnus Damm <damm@bitsmart.com> - * - * minor modifications by - * Wolfgang Denk <wd@denx.de> - */ - -#include <common.h> -#include <watchdog.h> -#include <command.h> -#include <asm/cache.h> -#include <asm/ppc4xx.h> -#include <netdev.h> - -DECLARE_GLOBAL_DATA_PTR; - -void board_reset(void); - -/* - * To provide an interface to detect CPU number for boards that support - * more then one CPU, we implement the "weak" default functions here. - * - * Returns CPU number - */ -int __get_cpu_num(void) -{ - return NA_OR_UNKNOWN_CPU; -} -int get_cpu_num(void) __attribute__((weak, alias("__get_cpu_num"))); - -#if defined(CONFIG_PCI) -#if defined(CONFIG_405GP) || \ - defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - -#define PCI_ASYNC - -static int pci_async_enabled(void) -{ -#if defined(CONFIG_405GP) - return (mfdcr(CPC0_PSR) & PSR_PCI_ASYNC_EN); -#endif - -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) - unsigned long val; - - mfsdr(SDR0_SDSTP1, val); - return (val & SDR0_SDSTP1_PAME_MASK); -#endif -} -#endif -#endif /* CONFIG_PCI */ - -#if defined(CONFIG_PCI) && !defined(CONFIG_IOP480) && \ - !defined(CONFIG_405) && !defined(CONFIG_405EX) -int pci_arbiter_enabled(void) -{ -#if defined(CONFIG_405GP) - return (mfdcr(CPC0_PSR) & PSR_PCI_ARBIT_EN); -#endif - -#if defined(CONFIG_405EP) - return (mfdcr(CPC0_PCI) & CPC0_PCI_ARBIT_EN); -#endif - -#if defined(CONFIG_440GP) - return (mfdcr(CPC0_STRP1) & CPC0_STRP1_PAE_MASK); -#endif - -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) - unsigned long val; - - mfsdr(SDR0_XCR0, val); - return (val & SDR0_XCR0_PAE_MASK); -#endif -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) - unsigned long val; - - mfsdr(SDR0_PCI0, val); - return (val & SDR0_PCI0_PAE_MASK); -#endif -} -#endif - -#if defined(CONFIG_405EP) -#define I2C_BOOTROM - -static int i2c_bootrom_enabled(void) -{ -#if defined(CONFIG_405EP) - return (mfdcr(CPC0_BOOT) & CPC0_BOOT_SEP); -#else - unsigned long val; - - mfsdr(SDR0_SDCS0, val); - return (val & SDR0_SDCS_SDD); -#endif -} -#endif - -#if defined(CONFIG_440GX) -#define SDR0_PINSTP_SHIFT 29 -static char *bootstrap_str[] = { - "EBC (16 bits)", - "EBC (8 bits)", - "EBC (32 bits)", - "EBC (8 bits)", - "PCI", - "I2C (Addr 0x54)", - "Reserved", - "I2C (Addr 0x50)", -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'B', 'D', 'E', 'x', 'F' }; -#endif - -#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) -#define SDR0_PINSTP_SHIFT 30 -static char *bootstrap_str[] = { - "EBC (8 bits)", - "PCI", - "I2C (Addr 0x54)", - "I2C (Addr 0x50)", -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'D'}; -#endif - -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) -#define SDR0_PINSTP_SHIFT 29 -static char *bootstrap_str[] = { - "EBC (8 bits)", - "PCI", - "NAND (8 bits)", - "EBC (16 bits)", - "EBC (16 bits)", - "I2C (Addr 0x54)", - "PCI", - "I2C (Addr 0x52)", -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' }; -#endif - -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#define SDR0_PINSTP_SHIFT 29 -static char *bootstrap_str[] = { - "EBC (8 bits)", - "EBC (16 bits)", - "EBC (16 bits)", - "NAND (8 bits)", - "PCI", - "I2C (Addr 0x54)", - "PCI", - "I2C (Addr 0x52)", -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' }; -#endif - -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) -#define SDR0_PINSTP_SHIFT 29 -static char *bootstrap_str[] = { - "EBC (8 bits)", - "EBC (16 bits)", - "PCI", - "PCI", - "EBC (16 bits)", - "NAND (8 bits)", - "I2C (Addr 0x54)", /* A8 */ - "I2C (Addr 0x52)", /* A4 */ -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }; -#endif - -#if defined(CONFIG_460SX) -#define SDR0_PINSTP_SHIFT 29 -static char *bootstrap_str[] = { - "EBC (8 bits)", - "EBC (16 bits)", - "EBC (32 bits)", - "NAND (8 bits)", - "I2C (Addr 0x54)", /* A8 */ - "I2C (Addr 0x52)", /* A4 */ -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G' }; -#endif - -#if defined(CONFIG_405EZ) -#define SDR0_PINSTP_SHIFT 28 -static char *bootstrap_str[] = { - "EBC (8 bits)", - "SPI (fast)", - "NAND (512 page, 4 addr cycle)", - "I2C (Addr 0x50)", - "EBC (32 bits)", - "I2C (Addr 0x50)", - "NAND (2K page, 5 addr cycle)", - "I2C (Addr 0x50)", - "EBC (16 bits)", - "Reserved", - "NAND (2K page, 4 addr cycle)", - "I2C (Addr 0x50)", - "NAND (512 page, 3 addr cycle)", - "I2C (Addr 0x50)", - "SPI (slow)", - "I2C (Addr 0x50)", -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', \ - 'I', 'x', 'K', 'L', 'M', 'N', 'O', 'P' }; -#endif - -#if defined(CONFIG_405EX) -#define SDR0_PINSTP_SHIFT 29 -static char *bootstrap_str[] = { - "EBC (8 bits)", - "EBC (16 bits)", - "EBC (16 bits)", - "NAND (8 bits)", - "NAND (8 bits)", - "I2C (Addr 0x54)", - "EBC (8 bits)", - "I2C (Addr 0x52)", -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' }; -#endif -#if defined(CONFIG_APM821XX) -#define SDR0_PINSTP_SHIFT 29 -static char *bootstrap_str[] = { - "RESERVED", - "RESERVED", - "RESERVED", - "NAND (8 bits)", - "NOR (8 bits)", - "NOR (8 bits) w/PLL Bypassed", - "I2C (Addr 0x54)", - "I2C (Addr 0x52)", -}; -static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }; -#endif - -#if defined(SDR0_PINSTP_SHIFT) -static int bootstrap_option(void) -{ - unsigned long val; - - mfsdr(SDR0_PINSTP, val); - return ((val & 0xf0000000) >> SDR0_PINSTP_SHIFT); -} -#endif /* SDR0_PINSTP_SHIFT */ - - -#if defined(CONFIG_440GP) -static int do_chip_reset (unsigned long sys0, unsigned long sys1) -{ - /* Changes to CPC0_SYS0 and CPC0_SYS1 require chip - * reset. - */ - mtdcr (CPC0_CR0, mfdcr (CPC0_CR0) | 0x80000000); /* Set SWE */ - mtdcr (CPC0_SYS0, sys0); - mtdcr (CPC0_SYS1, sys1); - mtdcr (CPC0_CR0, mfdcr (CPC0_CR0) & ~0x80000000); /* Clr SWE */ - mtspr (SPRN_DBCR0, 0x20000000); /* Reset the chip */ - - return 1; -} -#endif /* CONFIG_440GP */ - - -int checkcpu (void) -{ -#if !defined(CONFIG_405) /* not used on Xilinx 405 FPGA implementations */ - uint pvr = get_pvr(); - ulong clock = gd->cpu_clk; - char buf[32]; -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) - u32 reg; -#endif - -#if !defined(CONFIG_IOP480) - char addstr[64] = ""; - sys_info_t sys_info; - int cpu_num; - - cpu_num = get_cpu_num(); - if (cpu_num >= 0) - printf("CPU%d: ", cpu_num); - else - puts("CPU: "); - - get_sys_info(&sys_info); - -#if defined(CONFIG_XILINX_440) - puts("IBM PowerPC "); -#else - puts("AMCC PowerPC "); -#endif - - switch (pvr) { - -#if !defined(CONFIG_440) - case PVR_405GP_RB: - puts("405GP Rev. B"); - break; - - case PVR_405GP_RC: - puts("405GP Rev. C"); - break; - - case PVR_405GP_RD: - puts("405GP Rev. D"); - break; - -#ifdef CONFIG_405GP - case PVR_405GP_RE: /* 405GP rev E and 405CR rev C have same PVR */ - puts("405GP Rev. E"); - break; -#endif - - case PVR_405CR_RA: - puts("405CR Rev. A"); - break; - - case PVR_405CR_RB: - puts("405CR Rev. B"); - break; - -#ifdef CONFIG_405CR - case PVR_405CR_RC: /* 405GP rev E and 405CR rev C have same PVR */ - puts("405CR Rev. C"); - break; -#endif - - case PVR_405GPR_RB: - puts("405GPr Rev. B"); - break; - - case PVR_405EP_RB: - puts("405EP Rev. B"); - break; - - case PVR_405EZ_RA: - puts("405EZ Rev. A"); - break; - - case PVR_405EX1_RA: - puts("405EX Rev. A"); - strcpy(addstr, "Security support"); - break; - - case PVR_405EXR2_RA: - puts("405EXr Rev. A"); - strcpy(addstr, "No Security support"); - break; - - case PVR_405EX1_RC: - puts("405EX Rev. C"); - strcpy(addstr, "Security support"); - break; - - case PVR_405EX2_RC: - puts("405EX Rev. C"); - strcpy(addstr, "No Security support"); - break; - - case PVR_405EXR1_RC: - puts("405EXr Rev. C"); - strcpy(addstr, "Security support"); - break; - - case PVR_405EXR2_RC: - puts("405EXr Rev. C"); - strcpy(addstr, "No Security support"); - break; - - case PVR_405EX1_RD: - puts("405EX Rev. D"); - strcpy(addstr, "Security support"); - break; - - case PVR_405EX2_RD: - puts("405EX Rev. D"); - strcpy(addstr, "No Security support"); - break; - - case PVR_405EXR1_RD: - puts("405EXr Rev. D"); - strcpy(addstr, "Security support"); - break; - - case PVR_405EXR2_RD: - puts("405EXr Rev. D"); - strcpy(addstr, "No Security support"); - break; - -#else /* CONFIG_440 */ - -#if defined(CONFIG_440GP) - case PVR_440GP_RB: - puts("440GP Rev. B"); - /* See errata 1.12: CHIP_4 */ - if ((mfdcr(CPC0_SYS0) != mfdcr(CPC0_STRP0)) || - (mfdcr(CPC0_SYS1) != mfdcr(CPC0_STRP1)) ){ - puts ( "\n\t CPC0_SYSx DCRs corrupted. " - "Resetting chip ...\n"); - udelay( 1000 * 1000 ); /* Give time for serial buf to clear */ - do_chip_reset ( mfdcr(CPC0_STRP0), - mfdcr(CPC0_STRP1) ); - } - break; - - case PVR_440GP_RC: - puts("440GP Rev. C"); - break; -#endif /* CONFIG_440GP */ - - case PVR_440GX_RA: - puts("440GX Rev. A"); - break; - - case PVR_440GX_RB: - puts("440GX Rev. B"); - break; - - case PVR_440GX_RC: - puts("440GX Rev. C"); - break; - - case PVR_440GX_RF: - puts("440GX Rev. F"); - break; - - case PVR_440EP_RA: - puts("440EP Rev. A"); - break; - -#ifdef CONFIG_440EP - case PVR_440EP_RB: /* 440EP rev B and 440GR rev A have same PVR */ - puts("440EP Rev. B"); - break; - - case PVR_440EP_RC: /* 440EP rev C and 440GR rev B have same PVR */ - puts("440EP Rev. C"); - break; -#endif /* CONFIG_440EP */ - -#ifdef CONFIG_440GR - case PVR_440GR_RA: /* 440EP rev B and 440GR rev A have same PVR */ - puts("440GR Rev. A"); - break; - - case PVR_440GR_RB: /* 440EP rev C and 440GR rev B have same PVR */ - puts("440GR Rev. B"); - break; -#endif /* CONFIG_440GR */ - -#ifdef CONFIG_440EPX - case PVR_440EPX1_RA: /* 440EPx rev A and 440GRx rev A have same PVR */ - puts("440EPx Rev. A"); - strcpy(addstr, "Security/Kasumi support"); - break; - - case PVR_440EPX2_RA: /* 440EPx rev A and 440GRx rev A have same PVR */ - puts("440EPx Rev. A"); - strcpy(addstr, "No Security/Kasumi support"); - break; -#endif /* CONFIG_440EPX */ - -#ifdef CONFIG_440GRX - case PVR_440GRX1_RA: /* 440EPx rev A and 440GRx rev A have same PVR */ - puts("440GRx Rev. A"); - strcpy(addstr, "Security/Kasumi support"); - break; - - case PVR_440GRX2_RA: /* 440EPx rev A and 440GRx rev A have same PVR */ - puts("440GRx Rev. A"); - strcpy(addstr, "No Security/Kasumi support"); - break; -#endif /* CONFIG_440GRX */ - - case PVR_440SP_6_RAB: - puts("440SP Rev. A/B"); - strcpy(addstr, "RAID 6 support"); - break; - - case PVR_440SP_RAB: - puts("440SP Rev. A/B"); - strcpy(addstr, "No RAID 6 support"); - break; - - case PVR_440SP_6_RC: - puts("440SP Rev. C"); - strcpy(addstr, "RAID 6 support"); - break; - - case PVR_440SP_RC: - puts("440SP Rev. C"); - strcpy(addstr, "No RAID 6 support"); - break; - - case PVR_440SPe_6_RA: - puts("440SPe Rev. A"); - strcpy(addstr, "RAID 6 support"); - break; - - case PVR_440SPe_RA: - puts("440SPe Rev. A"); - strcpy(addstr, "No RAID 6 support"); - break; - - case PVR_440SPe_6_RB: - puts("440SPe Rev. B"); - strcpy(addstr, "RAID 6 support"); - break; - - case PVR_440SPe_RB: - puts("440SPe Rev. B"); - strcpy(addstr, "No RAID 6 support"); - break; - -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) - case PVR_460EX_RA: - puts("460EX Rev. A"); - strcpy(addstr, "No Security/Kasumi support"); - break; - - case PVR_460EX_SE_RA: - puts("460EX Rev. A"); - strcpy(addstr, "Security/Kasumi support"); - break; - - case PVR_460EX_RB: - puts("460EX Rev. B"); - mfsdr(SDR0_ECID3, reg); - if (reg & 0x00100000) - strcpy(addstr, "No Security/Kasumi support"); - else - strcpy(addstr, "Security/Kasumi support"); - break; - - case PVR_460GT_RA: - puts("460GT Rev. A"); - strcpy(addstr, "No Security/Kasumi support"); - break; - - case PVR_460GT_SE_RA: - puts("460GT Rev. A"); - strcpy(addstr, "Security/Kasumi support"); - break; - - case PVR_460GT_RB: - puts("460GT Rev. B"); - mfsdr(SDR0_ECID3, reg); - if (reg & 0x00100000) - strcpy(addstr, "No Security/Kasumi support"); - else - strcpy(addstr, "Security/Kasumi support"); - break; -#endif - - case PVR_460SX_RA: - puts("460SX Rev. A"); - strcpy(addstr, "Security support"); - break; - - case PVR_460SX_RA_V1: - puts("460SX Rev. A"); - strcpy(addstr, "No Security support"); - break; - - case PVR_460GX_RA: - puts("460GX Rev. A"); - strcpy(addstr, "Security support"); - break; - - case PVR_460GX_RA_V1: - puts("460GX Rev. A"); - strcpy(addstr, "No Security support"); - break; - - case PVR_APM821XX_RA: - puts("APM821XX Rev. A"); - strcpy(addstr, "Security support"); - break; - - case PVR_VIRTEX5: - puts("440x5 VIRTEX5"); - break; -#endif /* CONFIG_440 */ - - default: - printf (" UNKNOWN (PVR=%08x)", pvr); - break; - } - - printf (" at %s MHz (PLB=%lu OPB=%lu EBC=%lu", - strmhz(buf, clock), - sys_info.freqPLB / 1000000, - get_OPB_freq() / 1000000, - sys_info.freqEBC / 1000000); -#if defined(CONFIG_PCI) && \ - (defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX)) - printf(" PCI=%lu MHz", sys_info.freqPCI / 1000000); -#endif - printf(")\n"); - - if (addstr[0] != 0) - printf(" %s\n", addstr); - -#if defined(I2C_BOOTROM) - printf (" I2C boot EEPROM %sabled\n", i2c_bootrom_enabled() ? "en" : "dis"); -#endif /* I2C_BOOTROM */ -#if defined(SDR0_PINSTP_SHIFT) - printf (" Bootstrap Option %c - ", bootstrap_char[bootstrap_option()]); - printf ("Boot ROM Location %s", bootstrap_str[bootstrap_option()]); -#ifdef CONFIG_NAND_U_BOOT - puts(", booting from NAND"); -#endif /* CONFIG_NAND_U_BOOT */ - putc('\n'); -#endif /* SDR0_PINSTP_SHIFT */ - -#if defined(CONFIG_PCI) && !defined(CONFIG_405EX) - printf (" Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis"); -#endif - -#if defined(CONFIG_PCI) && defined(PCI_ASYNC) - if (pci_async_enabled()) { - printf (", PCI async ext clock used"); - } else { - printf (", PCI sync clock at %lu MHz", - sys_info.freqPLB / sys_info.pllPciDiv / 1000000); - } -#endif - -#if defined(CONFIG_PCI) && !defined(CONFIG_405EX) - putc('\n'); -#endif - -#if defined(CONFIG_405EP) || defined(CONFIG_405EZ) || defined(CONFIG_405EX) - printf (" 16 kB I-Cache 16 kB D-Cache"); -#elif defined(CONFIG_440) - printf (" 32 kB I-Cache 32 kB D-Cache"); -#else - printf (" 16 kB I-Cache %d kB D-Cache", - ((pvr | 0x00000001) == PVR_405GPR_RB) ? 16 : 8); -#endif -#endif /* !defined(CONFIG_IOP480) */ - -#if defined(CONFIG_IOP480) - printf ("PLX IOP480 (PVR=%08x)", pvr); - printf (" at %s MHz:", strmhz(buf, clock)); - printf (" %u kB I-Cache", 4); - printf (" %u kB D-Cache", 2); -#endif - -#endif /* !defined(CONFIG_405) */ - - putc ('\n'); - - return 0; -} - -int ppc440spe_revB() { - unsigned int pvr; - - pvr = get_pvr(); - if ((pvr == PVR_440SPe_6_RB) || (pvr == PVR_440SPe_RB)) - return 1; - else - return 0; -} - -/* ------------------------------------------------------------------------- */ - -int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ -#if defined(CONFIG_BOARD_RESET) - board_reset(); -#else -#if defined(CONFIG_SYS_4xx_RESET_TYPE) - mtspr(SPRN_DBCR0, CONFIG_SYS_4xx_RESET_TYPE << 28); -#else - /* - * Initiate system reset in debug control register DBCR - */ - mtspr(SPRN_DBCR0, 0x30000000); -#endif /* defined(CONFIG_SYS_4xx_RESET_TYPE) */ -#endif /* defined(CONFIG_BOARD_RESET) */ - - return 1; -} - - -/* - * Get timebase clock frequency - */ -unsigned long get_tbclk (void) -{ -#if !defined(CONFIG_IOP480) - sys_info_t sys_info; - - get_sys_info(&sys_info); - return (sys_info.freqProcessor); -#else - return (66000000); -#endif - -} - - -#if defined(CONFIG_WATCHDOG) -void watchdog_reset(void) -{ - int re_enable = disable_interrupts(); - reset_4xx_watchdog(); - if (re_enable) enable_interrupts(); -} - -void reset_4xx_watchdog(void) -{ - /* - * Clear TSR(WIS) bit - */ - mtspr(SPRN_TSR, 0x40000000); -} -#endif /* CONFIG_WATCHDOG */ - -/* - * Initializes on-chip ethernet controllers. - * to override, implement board_eth_init() - */ -int cpu_eth_init(bd_t *bis) -{ -#if defined(CONFIG_PPC4xx_EMAC) - ppc_4xx_eth_initialize(bis); -#endif - return 0; -} diff --git a/arch/powerpc/cpu/ppc4xx/cpu_init.c b/arch/powerpc/cpu/ppc4xx/cpu_init.c deleted file mode 100644 index bf208ad..0000000 --- a/arch/powerpc/cpu/ppc4xx/cpu_init.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * (C) Copyright 2000-2007 - * 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 <common.h> -#include <watchdog.h> -#include <asm/ppc4xx-emac.h> -#include <asm/processor.h> -#include <asm/ppc4xx-gpio.h> -#include <asm/ppc4xx.h> - -#if defined(CONFIG_405GP) || defined(CONFIG_405EP) -DECLARE_GLOBAL_DATA_PTR; -#endif - -#ifndef CONFIG_SYS_PLL_RECONFIG -#define CONFIG_SYS_PLL_RECONFIG 0 -#endif - -#if defined(CONFIG_440EPX) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) -static void reset_with_rli(void) -{ - u32 reg; - - /* - * Set reload inhibit so configuration will persist across - * processor resets - */ - mfcpr(CPR0_ICFG, reg); - reg |= CPR0_ICFG_RLI_MASK; - mtcpr(CPR0_ICFG, reg); - - /* Reset processor if configuration changed */ - __asm__ __volatile__ ("sync; isync"); - mtspr(SPRN_DBCR0, 0x20000000); -} -#endif - -void reconfigure_pll(u32 new_cpu_freq) -{ -#if defined(CONFIG_440EPX) - int reset_needed = 0; - u32 reg, temp; - u32 prbdv0, target_prbdv0, /* CLK_PRIMBD */ - fwdva, target_fwdva, fwdvb, target_fwdvb, /* CLK_PLLD */ - fbdv, target_fbdv, lfbdv, target_lfbdv, - perdv0, target_perdv0, /* CLK_PERD */ - spcid0, target_spcid0; /* CLK_SPCID */ - - /* Reconfigure clocks if necessary. - * See PPC440EPx User's Manual, sections 8.2 and 14 */ - if (new_cpu_freq == 667) { - target_prbdv0 = 2; - target_fwdva = 2; - target_fwdvb = 4; - target_fbdv = 20; - target_lfbdv = 1; - target_perdv0 = 4; - target_spcid0 = 4; - - mfcpr(CPR0_PRIMBD0, reg); - temp = (reg & PRBDV_MASK) >> 24; - prbdv0 = temp ? temp : 8; - if (prbdv0 != target_prbdv0) { - reg &= ~PRBDV_MASK; - reg |= ((target_prbdv0 == 8 ? 0 : target_prbdv0) << 24); - mtcpr(CPR0_PRIMBD0, reg); - reset_needed = 1; - } - - mfcpr(CPR0_PLLD, reg); - - temp = (reg & PLLD_FWDVA_MASK) >> 16; - fwdva = temp ? temp : 16; - - temp = (reg & PLLD_FWDVB_MASK) >> 8; - fwdvb = temp ? temp : 8; - - temp = (reg & PLLD_FBDV_MASK) >> 24; - fbdv = temp ? temp : 32; - - temp = (reg & PLLD_LFBDV_MASK); - lfbdv = temp ? temp : 64; - - if (fwdva != target_fwdva || fbdv != target_fbdv || lfbdv != target_lfbdv) { - reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK | - PLLD_FBDV_MASK | PLLD_LFBDV_MASK); - reg |= ((target_fwdva == 16 ? 0 : target_fwdva) << 16) | - ((target_fwdvb == 8 ? 0 : target_fwdvb) << 8) | - ((target_fbdv == 32 ? 0 : target_fbdv) << 24) | - (target_lfbdv == 64 ? 0 : target_lfbdv); - mtcpr(CPR0_PLLD, reg); - reset_needed = 1; - } - - mfcpr(CPR0_PERD, reg); - perdv0 = (reg & CPR0_PERD_PERDV0_MASK) >> 24; - if (perdv0 != target_perdv0) { - reg &= ~CPR0_PERD_PERDV0_MASK; - reg |= (target_perdv0 << 24); - mtcpr(CPR0_PERD, reg); - reset_needed = 1; - } - - mfcpr(CPR0_SPCID, reg); - temp = (reg & CPR0_SPCID_SPCIDV0_MASK) >> 24; - spcid0 = temp ? temp : 4; - if (spcid0 != target_spcid0) { - reg &= ~CPR0_SPCID_SPCIDV0_MASK; - reg |= ((target_spcid0 == 4 ? 0 : target_spcid0) << 24); - mtcpr(CPR0_SPCID, reg); - reset_needed = 1; - } - } - - /* Get current value of FWDVA.*/ - mfcpr(CPR0_PLLD, reg); - temp = (reg & PLLD_FWDVA_MASK) >> 16; - - /* - * Check to see if FWDVA has been set to value of 1. if it has we must - * modify it. - */ - if (temp == 1) { - /* - * Load register that contains current boot strapping option. - */ - mfcpr(CPR0_ICFG, reg); - /* - * Strapping option bits (ICS) are already in correct position, - * only masking needed. - */ - reg &= CPR0_ICFG_ICS_MASK; - - if ((reg == BOOT_STRAP_OPTION_A) || (reg == BOOT_STRAP_OPTION_B) || - (reg == BOOT_STRAP_OPTION_D) || (reg == BOOT_STRAP_OPTION_E)) { - mfcpr(CPR0_PLLD, reg); - - /* Get current value of fbdv. */ - temp = (reg & PLLD_FBDV_MASK) >> 24; - fbdv = temp ? temp : 32; - - /* Get current value of lfbdv. */ - temp = (reg & PLLD_LFBDV_MASK); - lfbdv = temp ? temp : 64; - - /* - * Get current value of FWDVA. Assign current FWDVA to - * new FWDVB. - */ - mfcpr(CPR0_PLLD, reg); - target_fwdvb = (reg & PLLD_FWDVA_MASK) >> 16; - fwdvb = target_fwdvb ? target_fwdvb : 8; - - /* - * Get current value of FWDVB. Assign current FWDVB to - * new FWDVA. - */ - target_fwdva = (reg & PLLD_FWDVB_MASK) >> 8; - fwdva = target_fwdva ? target_fwdva : 16; - - /* - * Update CPR0_PLLD with switched FWDVA and FWDVB. - */ - reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK | - PLLD_FBDV_MASK | PLLD_LFBDV_MASK); - reg |= ((fwdva == 16 ? 0 : fwdva) << 16) | - ((fwdvb == 8 ? 0 : fwdvb) << 8) | - ((fbdv == 32 ? 0 : fbdv) << 24) | - (lfbdv == 64 ? 0 : lfbdv); - mtcpr(CPR0_PLLD, reg); - - /* Acknowledge that a reset is required. */ - reset_needed = 1; - } - } - - /* Now reset the CPU if needed */ - if (reset_needed) - reset_with_rli(); -#endif - -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) - u32 reg; - - /* - * See "9.2.1.1 Booting with Option E" in the 460EX/GT - * users manual - */ - mfcpr(CPR0_PLLC, reg); - if ((reg & (CPR0_PLLC_RST | CPR0_PLLC_ENG)) == CPR0_PLLC_RST) { - /* - * Set engage bit - */ - reg = (reg & ~CPR0_PLLC_RST) | CPR0_PLLC_ENG; - mtcpr(CPR0_PLLC, reg); - - /* Now reset the CPU */ - reset_with_rli(); - } -#endif -} - -/* - * Breath some life into the CPU... - * - * Reconfigure PLL if necessary, - * set up the memory map, - * initialize a bunch of registers - */ -void -cpu_init_f (void) -{ -#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX) - u32 val; -#endif - - reconfigure_pll(CONFIG_SYS_PLL_RECONFIG); - -#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && \ - !defined(CONFIG_APM821XX) &&!defined(CONFIG_SYS_4xx_GPIO_TABLE) - /* - * GPIO0 setup (select GPIO or alternate function) - */ -#if defined(CONFIG_SYS_GPIO0_OR) - out32(GPIO0_OR, CONFIG_SYS_GPIO0_OR); /* set initial state of output pins */ -#endif -#if defined(CONFIG_SYS_GPIO0_ODR) - out32(GPIO0_ODR, CONFIG_SYS_GPIO0_ODR); /* open-drain select */ -#endif - out32(GPIO0_OSRH, CONFIG_SYS_GPIO0_OSRH); /* output select */ - out32(GPIO0_OSRL, CONFIG_SYS_GPIO0_OSRL); - out32(GPIO0_ISR1H, CONFIG_SYS_GPIO0_ISR1H); /* input select */ - out32(GPIO0_ISR1L, CONFIG_SYS_GPIO0_ISR1L); - out32(GPIO0_TSRH, CONFIG_SYS_GPIO0_TSRH); /* three-state select */ - out32(GPIO0_TSRL, CONFIG_SYS_GPIO0_TSRL); -#if defined(CONFIG_SYS_GPIO0_ISR2H) - out32(GPIO0_ISR2H, CONFIG_SYS_GPIO0_ISR2H); - out32(GPIO0_ISR2L, CONFIG_SYS_GPIO0_ISR2L); -#endif -#if defined (CONFIG_SYS_GPIO0_TCR) - out32(GPIO0_TCR, CONFIG_SYS_GPIO0_TCR); /* enable output driver for outputs */ -#endif -#endif /* CONFIG_405EP ... && !CONFIG_SYS_4xx_GPIO_TABLE */ - -#if defined (CONFIG_405EP) - /* - * Set EMAC noise filter bits - */ - mtdcr(CPC0_EPCTL, CPC0_EPCTL_E0NFE | CPC0_EPCTL_E1NFE); -#endif /* CONFIG_405EP */ - -#if defined(CONFIG_SYS_4xx_GPIO_TABLE) - gpio_set_chip_configuration(); -#endif /* CONFIG_SYS_4xx_GPIO_TABLE */ - - /* - * External Bus Controller (EBC) Setup - */ -#if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR)) -#if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ - defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_405EX) || defined(CONFIG_405)) - /* - * Move the next instructions into icache, since these modify the flash - * we are running from! - */ - asm volatile(" bl 0f" ::: "lr"); - asm volatile("0: mflr 3" ::: "r3"); - asm volatile(" addi 4, 0, 14" ::: "r4"); - asm volatile(" mtctr 4" ::: "ctr"); - asm volatile("1: icbt 0, 3"); - asm volatile(" addi 3, 3, 32" ::: "r3"); - asm volatile(" bdnz 1b" ::: "ctr", "cr0"); - asm volatile(" addis 3, 0, 0x0" ::: "r3"); - asm volatile(" ori 3, 3, 0xA000" ::: "r3"); - asm volatile(" mtctr 3" ::: "ctr"); - asm volatile("2: bdnz 2b" ::: "ctr", "cr0"); -#endif - - mtebc(PB0AP, CONFIG_SYS_EBC_PB0AP); - mtebc(PB0CR, CONFIG_SYS_EBC_PB0CR); -#endif - -#if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 1)) - mtebc(PB1AP, CONFIG_SYS_EBC_PB1AP); - mtebc(PB1CR, CONFIG_SYS_EBC_PB1CR); -#endif - -#if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 2)) - mtebc(PB2AP, CONFIG_SYS_EBC_PB2AP); - mtebc(PB2CR, CONFIG_SYS_EBC_PB2CR); -#endif - -#if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 3)) - mtebc(PB3AP, CONFIG_SYS_EBC_PB3AP); - mtebc(PB3CR, CONFIG_SYS_EBC_PB3CR); -#endif - -#if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 4)) - mtebc(PB4AP, CONFIG_SYS_EBC_PB4AP); - mtebc(PB4CR, CONFIG_SYS_EBC_PB4CR); -#endif - -#if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 5)) - mtebc(PB5AP, CONFIG_SYS_EBC_PB5AP); - mtebc(PB5CR, CONFIG_SYS_EBC_PB5CR); -#endif - -#if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 6)) - mtebc(PB6AP, CONFIG_SYS_EBC_PB6AP); - mtebc(PB6CR, CONFIG_SYS_EBC_PB6CR); -#endif - -#if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 7)) - mtebc(PB7AP, CONFIG_SYS_EBC_PB7AP); - mtebc(PB7CR, CONFIG_SYS_EBC_PB7CR); -#endif - -#if defined (CONFIG_SYS_EBC_CFG) - mtebc(EBC0_CFG, CONFIG_SYS_EBC_CFG); -#endif - -#if defined(CONFIG_WATCHDOG) - val = mfspr(SPRN_TCR); -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) - val |= 0xb8000000; /* generate system reset after 1.34 seconds */ -#elif defined(CONFIG_440EPX) - val |= 0xb0000000; /* generate system reset after 1.34 seconds */ -#else - val |= 0xf0000000; /* generate system reset after 2.684 seconds */ -#endif -#if defined(CONFIG_SYS_4xx_RESET_TYPE) - val &= ~0x30000000; /* clear WRC bits */ - val |= CONFIG_SYS_4xx_RESET_TYPE << 28; /* set board specific WRC type */ -#endif - mtspr(SPRN_TCR, val); - - val = mfspr(SPRN_TSR); - val |= 0x80000000; /* enable watchdog timer */ - mtspr(SPRN_TSR, val); - - reset_4xx_watchdog(); -#endif /* CONFIG_WATCHDOG */ - -#if defined(CONFIG_440GX) - /* Take the GX out of compatibility mode - * Travis Sawyer, 9 Mar 2004 - * NOTE: 440gx user manual inconsistency here - * Compatibility mode and Ethernet Clock select are not - * correct in the manual - */ - mfsdr(SDR0_MFR, val); - val &= ~0x10000000; - mtsdr(SDR0_MFR,val); -#endif /* CONFIG_440GX */ - -#if defined(CONFIG_460EX) - /* - * Set SDR0_AHB_CFG[A2P_INCR4] (bit 24) and - * clear SDR0_AHB_CFG[A2P_PROT2] (bit 25) for a new 460EX errata - * regarding concurrent use of AHB USB OTG, USB 2.0 host and SATA - */ - mfsdr(SDR0_AHB_CFG, val); - val |= 0x80; - val &= ~0x40; - mtsdr(SDR0_AHB_CFG, val); - mfsdr(SDR0_USB2HOST_CFG, val); - val &= ~0xf00; - val |= 0x400; - mtsdr(SDR0_USB2HOST_CFG, val); -#endif /* CONFIG_460EX */ - -#if defined(CONFIG_405EX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ - defined(CONFIG_460SX) || defined(CONFIG_APM821XX) - /* - * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read - */ - mtdcr(PLB4A0_ACR, (mfdcr(PLB4A0_ACR) & ~PLB4Ax_ACR_RDP_MASK) | - PLB4Ax_ACR_RDP_4DEEP); - mtdcr(PLB4A1_ACR, (mfdcr(PLB4A1_ACR) & ~PLB4Ax_ACR_RDP_MASK) | - PLB4Ax_ACR_RDP_4DEEP); -#endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */ -} - -/* - * initialize higher level parts of CPU like time base and timers - */ -int cpu_init_r (void) -{ -#if defined(CONFIG_405GP) - uint pvr = get_pvr(); - - /* - * Set edge conditioning circuitry on PPC405GPr - * for compatibility to existing PPC405GP designs. - */ - if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) { - mtdcr(CPC0_ECR, 0x60606000); - } -#endif /* defined(CONFIG_405GP) */ - - return 0; -} - -#if defined(CONFIG_PCI) && \ - (defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX)) -/* - * 440EP(x)/GR(x) PCI async/sync clocking restriction: - * - * In asynchronous PCI mode, the synchronous PCI clock must meet - * certain requirements. The following equation describes the - * relationship that must be maintained between the asynchronous PCI - * clock and synchronous PCI clock. Select an appropriate PCI:PLB - * ratio to maintain the relationship: - * - * AsyncPCIClk - 1MHz <= SyncPCIclock <= (2 * AsyncPCIClk) - 1MHz - */ -static int ppc4xx_pci_sync_clock_ok(u32 sync, u32 async) -{ - if (((async - 1000000) > sync) || (sync > ((2 * async) - 1000000))) - return 0; - else - return 1; -} - -int ppc4xx_pci_sync_clock_config(u32 async) -{ - sys_info_t sys_info; - u32 sync; - int div; - u32 reg; - u32 spcid_val[] = { - CPR0_SPCID_SPCIDV0_DIV1, CPR0_SPCID_SPCIDV0_DIV2, - CPR0_SPCID_SPCIDV0_DIV3, CPR0_SPCID_SPCIDV0_DIV4 }; - - get_sys_info(&sys_info); - sync = sys_info.freqPCI; - - /* - * First check if the equation above is met - */ - if (!ppc4xx_pci_sync_clock_ok(sync, async)) { - /* - * Reconfigure PCI sync clock to meet the equation. - * Start with highest possible PCI sync frequency - * (divider 1). - */ - for (div = 1; div <= 4; div++) { - sync = sys_info.freqPLB / div; - if (ppc4xx_pci_sync_clock_ok(sync, async)) - break; - } - - if (div <= 4) { - mtcpr(CPR0_SPCID, spcid_val[div]); - - mfcpr(CPR0_ICFG, reg); - reg |= CPR0_ICFG_RLI_MASK; - mtcpr(CPR0_ICFG, reg); - - /* do chip reset */ - mtspr(SPRN_DBCR0, 0x20000000); - } else { - /* Impossible to configure the PCI sync clock */ - return -1; - } - } - - return 0; -} -#endif diff --git a/arch/powerpc/cpu/ppc4xx/dcr.S b/arch/powerpc/cpu/ppc4xx/dcr.S deleted file mode 100644 index e668e05..0000000 --- a/arch/powerpc/cpu/ppc4xx/dcr.S +++ /dev/null @@ -1,198 +0,0 @@ -/* - * (C) Copyright 2001 - * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <config.h> - -#if defined(CONFIG_4xx) && defined(CONFIG_CMD_SETGETDCR) - -#include <asm/ppc4xx.h> - -#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ - -#include <ppc_asm.tmpl> -#include <ppc_defs.h> - -#include <asm/cache.h> -#include <asm/mmu.h> - -#define _ASMLANGUAGE - -/***************************************************************************** - * - * XXX - DANGER - * These routines make use of self modifying code. DO NOT CALL THEM - * UNTIL THEY ARE RELOCATED TO RAM. Additionally, I do not - * recommend them for use in anything other than an interactive - * debugging environment. This is mainly due to performance reasons. - * - ****************************************************************************/ - -/* - * static void _create_MFDCR(unsigned short dcrn) - * - * Builds a 'mfdcr' instruction for get_dcr - * function. - */ - .section ".text" - .align 2 - .type _create_MFDCR,@function -_create_MFDCR: - /* - * Build up a 'mfdcr' instruction formatted as follows: - * - * OPCD | RT | DCRF | XO | CR | - * ---------------|--------------|--------------|----| - * 0 5 | 6 10 | 11 20 | 21 30 | 31 | - * | | DCRN | | | - * 31 | %r3 | (5..9|0..4) | 323 | 0 | - * - * Where: - * OPCD = opcode - 31 - * RT = destination register - %r3 return register - * DCRF = DCRN # with upper and lower halves swapped - * XO = extended opcode - 323 - * CR = CR[CR0] NOT undefined - 0 - */ - rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */ - rlwinm r3, r3, 5, 22, 26 - or r3, r3, r0 - slwi r3, r3, 10 - oris r3, r3, 0x3e30 /* RT = %r3 */ - ori r3, r3, 323 /* XO = 323 */ - slwi r3, r3, 1 /* CR = 0 */ - - mflr r4 - stw r3, 0(r4) /* Store instr in get_dcr() */ - dcbst r0, r4 /* Make sure val is written out */ - sync /* Wait for write to complete */ - icbi r0, r4 /* Make sure old instr is dumped */ - isync /* Wait for icbi to complete */ - - blr -.Lfe1: .size _create_MFDCR,.Lfe1-_create_MFDCR -/* end _create_MFDCR() */ - -/* - * static void _create_MTDCR(unsigned short dcrn, unsigned long value) - * - * Builds a 'mtdcr' instruction for set_dcr - * function. - */ - .section ".text" - .align 2 - .type _create_MTDCR,@function -_create_MTDCR: - /* - * Build up a 'mtdcr' instruction formatted as follows: - * - * OPCD | RS | DCRF | XO | CR | - * ---------------|--------------|--------------|----| - * 0 5 | 6 10 | 11 20 | 21 30 | 31 | - * | | DCRN | | | - * 31 | %r3 | (5..9|0..4) | 451 | 0 | - * - * Where: - * OPCD = opcode - 31 - * RS = source register - %r4 - * DCRF = dest. DCRN # with upper and lower halves swapped - * XO = extended opcode - 451 - * CR = CR[CR0] NOT undefined - 0 - */ - rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */ - rlwinm r3, r3, 5, 22, 26 - or r3, r3, r0 - slwi r3, r3, 10 - oris r3, r3, 0x3e40 /* RS = %r4 */ - ori r3, r3, 451 /* XO = 451 */ - slwi r3, r3, 1 /* CR = 0 */ - - mflr r5 - stw r3, 0(r5) /* Store instr in set_dcr() */ - dcbst r0, r5 /* Make sure val is written out */ - sync /* Wait for write to complete */ - icbi r0, r5 /* Make sure old instr is dumped */ - isync /* Wait for icbi to complete */ - - blr -.Lfe2: .size _create_MTDCR,.Lfe2-_create_MTDCR -/* end _create_MTDCR() */ - - -/* - * unsigned long get_dcr(unsigned short dcrn) - * - * Return a given DCR's value. - */ - /* */ - /* XXX - This is self modifying code, hence */ - /* it is in the data section. */ - /* */ - .section ".data" - .align 2 - .globl get_dcr - .type get_dcr,@function -get_dcr: - mflr r0 /* Get link register */ - stwu r1, -32(r1) /* Save back chain and move SP */ - stw r0, +36(r1) /* Save link register */ - - bl _create_MFDCR /* Build following instruction */ - /* XXX - we build this instuction up on the fly. */ - .long 0 /* Get DCR's value */ - - lwz r0, +36(r1) /* Get saved link register */ - mtlr r0 /* Restore link register */ - addi r1, r1, +32 /* Remove frame from stack */ - blr /* Return to calling function */ -.Lfe3: .size get_dcr,.Lfe3-get_dcr -/* end get_dcr() */ - - -/* - * unsigned void set_dcr(unsigned short dcrn, unsigned long value) - * - * Return a given DCR's value. - */ - /* - * XXX - This is self modifying code, hence - * it is in the data section. - */ - .section ".data" - .align 2 - .globl set_dcr - .type set_dcr,@function -set_dcr: - mflr r0 /* Get link register */ - stwu r1, -32(r1) /* Save back chain and move SP */ - stw r0, +36(r1) /* Save link register */ - - bl _create_MTDCR /* Build following instruction */ - /* XXX - we build this instuction up on the fly. */ - .long 0 /* Set DCR's value */ - - lwz r0, +36(r1) /* Get saved link register */ - mtlr r0 /* Restore link register */ - addi r1, r1, +32 /* Remove frame from stack */ - blr /* Return to calling function */ -.Lfe4: .size set_dcr,.Lfe4-set_dcr -/* end set_dcr() */ -#endif diff --git a/arch/powerpc/cpu/ppc4xx/denali_data_eye.c b/arch/powerpc/cpu/ppc4xx/denali_data_eye.c deleted file mode 100644 index 9bba0ca..0000000 --- a/arch/powerpc/cpu/ppc4xx/denali_data_eye.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * arch/powerpc/cpu/ppc4xx/denali_data_eye.c - * Extracted from board/amcc/sequoia/sdram.c by Larry Johnson <lrj@acm.org>. - * - * (C) Copyright 2006 - * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com - * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com - * Thierry Roman, AMCC/IBM, thierry_roman@fr.ibm.com - * Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com - * Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com - * - * (C) Copyright 2006-2007 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * 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 - */ - -/* define DEBUG for debugging output (obviously ;-)) */ -#if 0 -#define DEBUG -#endif - -#include <common.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <asm/ppc4xx.h> - -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -/*-----------------------------------------------------------------------------+ - * denali_wait_for_dlllock. - +----------------------------------------------------------------------------*/ -int denali_wait_for_dlllock(void) -{ - u32 val; - int wait; - - /* -----------------------------------------------------------+ - * Wait for the DCC master delay line to finish calibration - * ----------------------------------------------------------*/ - for (wait = 0; wait != 0xffff; ++wait) { - mfsdram(DDR0_17, val); - if (DDR0_17_DLLLOCKREG_DECODE(val)) { - /* dlllockreg bit on */ - return 0; - } - } - debug("0x%04x: DDR0_17 Value (dlllockreg bit): 0x%08x\n", wait, val); - debug("Waiting for dlllockreg bit to raise\n"); - return -1; -} - -#if defined(CONFIG_DDR_DATA_EYE) -#define DDR_DCR_BASE 0x10 -#define ddrcfga (DDR_DCR_BASE+0x0) /* DDR configuration address reg */ -#define ddrcfgd (DDR_DCR_BASE+0x1) /* DDR configuration data reg */ - -/*-----------------------------------------------------------------------------+ - * wait_for_dram_init_complete. - +----------------------------------------------------------------------------*/ -static int wait_for_dram_init_complete(void) -{ - unsigned long val; - int wait = 0; - - /* --------------------------------------------------------------+ - * Wait for 'DRAM initialization complete' bit in status register - * -------------------------------------------------------------*/ - mtdcr(ddrcfga, DDR0_00); - - while (wait != 0xffff) { - val = mfdcr(ddrcfgd); - if ((val & DDR0_00_INT_STATUS_BIT6) == DDR0_00_INT_STATUS_BIT6) - /* 'DRAM initialization complete' bit */ - return 0; - else - wait++; - } - debug("DRAM initialization complete bit in status register did not " - "rise\n"); - return -1; -} - -#define NUM_TRIES 64 -#define NUM_READS 10 - -/*-----------------------------------------------------------------------------+ - * denali_core_search_data_eye. - +----------------------------------------------------------------------------*/ -void denali_core_search_data_eye(void) -{ - int k, j; - u32 val; - u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X; - u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0; - u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0; - u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0; - volatile u32 *ram_pointer; - u32 test[NUM_TRIES] = { - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 - }; - - ram_pointer = (volatile u32 *)(CONFIG_SYS_SDRAM_BASE); - - for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) { - /* for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) { */ - - /* -----------------------------------------------------------+ - * De-assert 'start' parameter. - * ----------------------------------------------------------*/ - mtdcr(ddrcfga, DDR0_02); - val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | - DDR0_02_START_OFF; - mtdcr(ddrcfgd, val); - - /* -----------------------------------------------------------+ - * Set 'wr_dqs_shift' - * ----------------------------------------------------------*/ - mtdcr(ddrcfga, DDR0_09); - val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) | - DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift); - mtdcr(ddrcfgd, val); - - /* -----------------------------------------------------------+ - * Set 'dqs_out_shift' = wr_dqs_shift + 32 - * ----------------------------------------------------------*/ - dqs_out_shift = wr_dqs_shift + 32; - mtdcr(ddrcfga, DDR0_22); - val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) | - DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift); - mtdcr(ddrcfgd, val); - - passing_cases = 0; - - for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64; - dll_dqs_delay_X++) { - /* for (dll_dqs_delay_X=1; dll_dqs_delay_X<128; - dll_dqs_delay_X++) { */ - /* -----------------------------------------------------------+ - * Set 'dll_dqs_delay_X'. - * ----------------------------------------------------------*/ - /* dll_dqs_delay_0 */ - mtdcr(ddrcfga, DDR0_17); - val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK) - | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X); - mtdcr(ddrcfgd, val); - /* dll_dqs_delay_1 to dll_dqs_delay_4 */ - mtdcr(ddrcfga, DDR0_18); - val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK) - | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X) - | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X) - | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X) - | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X); - mtdcr(ddrcfgd, val); - /* dll_dqs_delay_5 to dll_dqs_delay_8 */ - mtdcr(ddrcfga, DDR0_19); - val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK) - | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X) - | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X) - | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X) - | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X); - mtdcr(ddrcfgd, val); - /* clear any ECC errors */ - mtdcr(ddrcfga, DDR0_00); - mtdcr(ddrcfgd, - mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C)); - - sync(); - eieio(); - - /* -----------------------------------------------------------+ - * Assert 'start' parameter. - * ----------------------------------------------------------*/ - mtdcr(ddrcfga, DDR0_02); - val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | - DDR0_02_START_ON; - mtdcr(ddrcfgd, val); - - sync(); - eieio(); - - /* -----------------------------------------------------------+ - * Wait for the DCC master delay line to finish calibration - * ----------------------------------------------------------*/ - if (denali_wait_for_dlllock() != 0) { - printf("dll lock did not occur !!!\n"); - printf("denali_core_search_data_eye!!!\n"); - printf("wr_dqs_shift = %d - dll_dqs_delay_X = " - "%d\n", wr_dqs_shift, dll_dqs_delay_X); - hang(); - } - sync(); - eieio(); - - if (wait_for_dram_init_complete() != 0) { - printf("dram init complete did not occur!!!\n"); - printf("denali_core_search_data_eye!!!\n"); - printf("wr_dqs_shift = %d - dll_dqs_delay_X = " - "%d\n", wr_dqs_shift, dll_dqs_delay_X); - hang(); - } - udelay(100); /* wait 100us to ensure init is really completed !!! */ - - /* write values */ - for (j = 0; j < NUM_TRIES; j++) { - ram_pointer[j] = test[j]; - - /* clear any cache at ram location */ - __asm__("dcbf 0,%0": :"r"(&ram_pointer[j])); - } - - /* read values back */ - for (j = 0; j < NUM_TRIES; j++) { - for (k = 0; k < NUM_READS; k++) { - /* clear any cache at ram location */ - __asm__("dcbf 0,%0": :"r"(&ram_pointer - [j])); - - if (ram_pointer[j] != test[j]) - break; - } - - /* read error */ - if (k != NUM_READS) - break; - } - - /* See if the dll_dqs_delay_X value passed. */ - mtdcr(ddrcfga, DDR0_00); - if (j < NUM_TRIES - || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) & - 0x3F)) { - /* Failed */ - passing_cases = 0; - /* break; */ - } else { - /* Passed */ - if (passing_cases == 0) - dll_dqs_delay_X_sw_val = - dll_dqs_delay_X; - passing_cases++; - if (passing_cases >= max_passing_cases) { - max_passing_cases = passing_cases; - wr_dqs_shift_with_max_passing_cases = - wr_dqs_shift; - dll_dqs_delay_X_start_window = - dll_dqs_delay_X_sw_val; - dll_dqs_delay_X_end_window = - dll_dqs_delay_X; - } - } - - /* -----------------------------------------------------------+ - * De-assert 'start' parameter. - * ----------------------------------------------------------*/ - mtdcr(ddrcfga, DDR0_02); - val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | - DDR0_02_START_OFF; - mtdcr(ddrcfgd, val); - } /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */ - } /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */ - - /* -----------------------------------------------------------+ - * Largest passing window is now detected. - * ----------------------------------------------------------*/ - - /* Compute dll_dqs_delay_X value */ - dll_dqs_delay_X = (dll_dqs_delay_X_end_window + - dll_dqs_delay_X_start_window) / 2; - wr_dqs_shift = wr_dqs_shift_with_max_passing_cases; - - debug("DQS calibration - Window detected:\n"); - debug("max_passing_cases = %d\n", max_passing_cases); - debug("wr_dqs_shift = %d\n", wr_dqs_shift); - debug("dll_dqs_delay_X = %d\n", dll_dqs_delay_X); - debug("dll_dqs_delay_X window = %d - %d\n", - dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window); - - /* -----------------------------------------------------------+ - * De-assert 'start' parameter. - * ----------------------------------------------------------*/ - mtdcr(ddrcfga, DDR0_02); - val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF; - mtdcr(ddrcfgd, val); - - /* -----------------------------------------------------------+ - * Set 'wr_dqs_shift' - * ----------------------------------------------------------*/ - mtdcr(ddrcfga, DDR0_09); - val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) - | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift); - mtdcr(ddrcfgd, val); - debug("DDR0_09=0x%08lx\n", val); - - /* -----------------------------------------------------------+ - * Set 'dqs_out_shift' = wr_dqs_shift + 32 - * ----------------------------------------------------------*/ - dqs_out_shift = wr_dqs_shift + 32; - mtdcr(ddrcfga, DDR0_22); - val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) - | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift); - mtdcr(ddrcfgd, val); - debug("DDR0_22=0x%08lx\n", val); - - /* -----------------------------------------------------------+ - * Set 'dll_dqs_delay_X'. - * ----------------------------------------------------------*/ - /* dll_dqs_delay_0 */ - mtdcr(ddrcfga, DDR0_17); - val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK) - | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X); - mtdcr(ddrcfgd, val); - debug("DDR0_17=0x%08lx\n", val); - - /* dll_dqs_delay_1 to dll_dqs_delay_4 */ - mtdcr(ddrcfga, DDR0_18); - val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK) - | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X) - | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X) - | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X) - | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X); - mtdcr(ddrcfgd, val); - debug("DDR0_18=0x%08lx\n", val); - - /* dll_dqs_delay_5 to dll_dqs_delay_8 */ - mtdcr(ddrcfga, DDR0_19); - val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK) - | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X) - | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X) - | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X) - | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X); - mtdcr(ddrcfgd, val); - debug("DDR0_19=0x%08lx\n", val); - - /* -----------------------------------------------------------+ - * Assert 'start' parameter. - * ----------------------------------------------------------*/ - mtdcr(ddrcfga, DDR0_02); - val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON; - mtdcr(ddrcfgd, val); - - sync(); - eieio(); - - /* -----------------------------------------------------------+ - * Wait for the DCC master delay line to finish calibration - * ----------------------------------------------------------*/ - if (denali_wait_for_dlllock() != 0) { - printf("dll lock did not occur !!!\n"); - hang(); - } - sync(); - eieio(); - - if (wait_for_dram_init_complete() != 0) { - printf("dram init complete did not occur !!!\n"); - hang(); - } - udelay(100); /* wait 100us to ensure init is really completed !!! */ -} -#endif /* defined(CONFIG_DDR_DATA_EYE) */ -#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */ diff --git a/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c b/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c deleted file mode 100644 index c35b113..0000000 --- a/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c +++ /dev/null @@ -1,1256 +0,0 @@ -/* - * arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c - * This SPD SDRAM detection code supports AMCC PPC44x CPUs with a Denali-core - * DDR2 controller, specifically the 440EPx/GRx. - * - * (C) Copyright 2007-2008 - * Larry Johnson, lrj@acm.org. - * - * Based primarily on arch/powerpc/cpu/ppc4xx/4xx_spd_ddr2.c, which is... - * - * (C) Copyright 2007 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * COPYRIGHT AMCC CORPORATION 2004 - * - * 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 - * - */ - -/* define DEBUG for debugging output (obviously ;-)) */ -#if 0 -#define DEBUG -#endif - -#include <common.h> -#include <command.h> -#include <asm/ppc4xx.h> -#include <i2c.h> -#include <asm/io.h> -#include <asm/processor.h> -#include <asm/mmu.h> -#include <asm/cache.h> - -#if defined(CONFIG_SPD_EEPROM) && \ - (defined(CONFIG_440EPX) || defined(CONFIG_440GRX)) - -/*-----------------------------------------------------------------------------+ - * Defines - *-----------------------------------------------------------------------------*/ -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define MAXDIMMS 2 -#define MAXRANKS 2 - -#define ONE_BILLION 1000000000 - -#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d)) - -#define DLL_DQS_DELAY 0x19 -#define DLL_DQS_BYPASS 0x0B -#define DQS_OUT_SHIFT 0x7F - -/* - * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory - * region. Right now the cache should still be disabled in U-Boot because of the - * EMAC driver, that need it's buffer descriptor to be located in non cached - * memory. - * - * If at some time this restriction doesn't apply anymore, just define - * CONFIG_4xx_DCACHE in the board config file and this code should setup - * everything correctly. - */ -#if defined(CONFIG_4xx_DCACHE) -#define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */ -#else -#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */ -#endif - -/*-----------------------------------------------------------------------------+ - * Prototypes - *-----------------------------------------------------------------------------*/ -extern int denali_wait_for_dlllock(void); -extern void denali_core_search_data_eye(void); -extern void dcbz_area(u32 start_address, u32 num_bytes); - -/* - * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed - */ -void __spd_ddr_init_hang(void) -{ - hang(); -} -void spd_ddr_init_hang(void) - __attribute__ ((weak, alias("__spd_ddr_init_hang"))); - -#if defined(DEBUG) -static void print_mcsr(void) -{ - printf("MCSR = 0x%08X\n", mfspr(SPRN_MCSR)); -} - -static void denali_sdram_register_dump(void) -{ - unsigned int sdram_data; - - printf("\n Register Dump:\n"); - mfsdram(DDR0_00, sdram_data); - printf(" DDR0_00 = 0x%08X", sdram_data); - mfsdram(DDR0_01, sdram_data); - printf(" DDR0_01 = 0x%08X\n", sdram_data); - mfsdram(DDR0_02, sdram_data); - printf(" DDR0_02 = 0x%08X", sdram_data); - mfsdram(DDR0_03, sdram_data); - printf(" DDR0_03 = 0x%08X\n", sdram_data); - mfsdram(DDR0_04, sdram_data); - printf(" DDR0_04 = 0x%08X", sdram_data); - mfsdram(DDR0_05, sdram_data); - printf(" DDR0_05 = 0x%08X\n", sdram_data); - mfsdram(DDR0_06, sdram_data); - printf(" DDR0_06 = 0x%08X", sdram_data); - mfsdram(DDR0_07, sdram_data); - printf(" DDR0_07 = 0x%08X\n", sdram_data); - mfsdram(DDR0_08, sdram_data); - printf(" DDR0_08 = 0x%08X", sdram_data); - mfsdram(DDR0_09, sdram_data); - printf(" DDR0_09 = 0x%08X\n", sdram_data); - mfsdram(DDR0_10, sdram_data); - printf(" DDR0_10 = 0x%08X", sdram_data); - mfsdram(DDR0_11, sdram_data); - printf(" DDR0_11 = 0x%08X\n", sdram_data); - mfsdram(DDR0_12, sdram_data); - printf(" DDR0_12 = 0x%08X", sdram_data); - mfsdram(DDR0_14, sdram_data); - printf(" DDR0_14 = 0x%08X\n", sdram_data); - mfsdram(DDR0_17, sdram_data); - printf(" DDR0_17 = 0x%08X", sdram_data); - mfsdram(DDR0_18, sdram_data); - printf(" DDR0_18 = 0x%08X\n", sdram_data); - mfsdram(DDR0_19, sdram_data); - printf(" DDR0_19 = 0x%08X", sdram_data); - mfsdram(DDR0_20, sdram_data); - printf(" DDR0_20 = 0x%08X\n", sdram_data); - mfsdram(DDR0_21, sdram_data); - printf(" DDR0_21 = 0x%08X", sdram_data); - mfsdram(DDR0_22, sdram_data); - printf(" DDR0_22 = 0x%08X\n", sdram_data); - mfsdram(DDR0_23, sdram_data); - printf(" DDR0_23 = 0x%08X", sdram_data); - mfsdram(DDR0_24, sdram_data); - printf(" DDR0_24 = 0x%08X\n", sdram_data); - mfsdram(DDR0_25, sdram_data); - printf(" DDR0_25 = 0x%08X", sdram_data); - mfsdram(DDR0_26, sdram_data); - printf(" DDR0_26 = 0x%08X\n", sdram_data); - mfsdram(DDR0_27, sdram_data); - printf(" DDR0_27 = 0x%08X", sdram_data); - mfsdram(DDR0_28, sdram_data); - printf(" DDR0_28 = 0x%08X\n", sdram_data); - mfsdram(DDR0_31, sdram_data); - printf(" DDR0_31 = 0x%08X", sdram_data); - mfsdram(DDR0_32, sdram_data); - printf(" DDR0_32 = 0x%08X\n", sdram_data); - mfsdram(DDR0_33, sdram_data); - printf(" DDR0_33 = 0x%08X", sdram_data); - mfsdram(DDR0_34, sdram_data); - printf(" DDR0_34 = 0x%08X\n", sdram_data); - mfsdram(DDR0_35, sdram_data); - printf(" DDR0_35 = 0x%08X", sdram_data); - mfsdram(DDR0_36, sdram_data); - printf(" DDR0_36 = 0x%08X\n", sdram_data); - mfsdram(DDR0_37, sdram_data); - printf(" DDR0_37 = 0x%08X", sdram_data); - mfsdram(DDR0_38, sdram_data); - printf(" DDR0_38 = 0x%08X\n", sdram_data); - mfsdram(DDR0_39, sdram_data); - printf(" DDR0_39 = 0x%08X", sdram_data); - mfsdram(DDR0_40, sdram_data); - printf(" DDR0_40 = 0x%08X\n", sdram_data); - mfsdram(DDR0_41, sdram_data); - printf(" DDR0_41 = 0x%08X", sdram_data); - mfsdram(DDR0_42, sdram_data); - printf(" DDR0_42 = 0x%08X\n", sdram_data); - mfsdram(DDR0_43, sdram_data); - printf(" DDR0_43 = 0x%08X", sdram_data); - mfsdram(DDR0_44, sdram_data); - printf(" DDR0_44 = 0x%08X\n", sdram_data); -} -#else -static inline void denali_sdram_register_dump(void) -{ -} - -inline static void print_mcsr(void) -{ -} -#endif /* defined(DEBUG) */ - -static int is_ecc_enabled(void) -{ - u32 val; - - mfsdram(DDR0_22, val); - return 0x3 == DDR0_22_CTRL_RAW_DECODE(val); -} - -static unsigned char spd_read(u8 chip, unsigned int addr) -{ - u8 data[2]; - - if (0 != i2c_probe(chip) || 0 != i2c_read(chip, addr, 1, data, 1)) { - debug("spd_read(0x%02X, 0x%02X) failed\n", chip, addr); - return 0; - } - debug("spd_read(0x%02X, 0x%02X) returned 0x%02X\n", - chip, addr, data[0]); - return data[0]; -} - -static unsigned long get_tcyc(unsigned char reg) -{ - /* - * Byte 9, et al: Cycle time for CAS Latency=X, is split into two - * nibbles: the higher order nibble (bits 4-7) designates the cycle time - * to a granularity of 1ns; the value presented by the lower order - * nibble (bits 0-3) has a granularity of .1ns and is added to the value - * designated by the higher nibble. In addition, four lines of the lower - * order nibble are assigned to support +.25, +.33, +.66, and +.75. - */ - - unsigned char subfield_b = reg & 0x0F; - - switch (subfield_b & 0x0F) { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - case 0x8: - case 0x9: - return 1000 * (reg >> 4) + 100 * subfield_b; - case 0xA: - return 1000 * (reg >> 4) + 250; - case 0xB: - return 1000 * (reg >> 4) + 333; - case 0xC: - return 1000 * (reg >> 4) + 667; - case 0xD: - return 1000 * (reg >> 4) + 750; - } - return 0; -} - -/*------------------------------------------------------------------ - * Find the installed DIMMs, make sure that the are DDR2, and fill - * in the dimm_ranks array. Then dimm_ranks[dimm_num] > 0 iff the - * DIMM and dimm_num is present. - * Note: Because there are only two chip-select lines, it is assumed - * that a board with a single socket can support two ranks on that - * socket, while a board with two sockets can support only one rank - * on each socket. - *-----------------------------------------------------------------*/ -static void get_spd_info(unsigned long dimm_ranks[], - unsigned long *ranks, - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long dimm_found = FALSE; - unsigned long const max_ranks_per_dimm = (1 == num_dimm_banks) ? 2 : 1; - unsigned char num_of_bytes; - unsigned char total_size; - - *ranks = 0; - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - num_of_bytes = 0; - total_size = 0; - - num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0); - total_size = spd_read(iic0_dimm_addr[dimm_num], 1); - if ((num_of_bytes != 0) && (total_size != 0)) { - unsigned char const dimm_type = - spd_read(iic0_dimm_addr[dimm_num], 2); - - unsigned long ranks_on_dimm = - (spd_read(iic0_dimm_addr[dimm_num], 5) & 0x07) + 1; - - if (8 != dimm_type) { - switch (dimm_type) { - case 1: - printf("ERROR: Standard Fast Page Mode " - "DRAM DIMM"); - break; - case 2: - printf("ERROR: EDO DIMM"); - break; - case 3: - printf("ERROR: Pipelined Nibble DIMM"); - break; - case 4: - printf("ERROR: SDRAM DIMM"); - break; - case 5: - printf("ERROR: Multiplexed ROM DIMM"); - break; - case 6: - printf("ERROR: SGRAM DIMM"); - break; - case 7: - printf("ERROR: DDR1 DIMM"); - break; - default: - printf("ERROR: Unknown DIMM (type %d)", - (unsigned int)dimm_type); - break; - } - printf(" detected in slot %lu.\n", dimm_num); - printf("Only DDR2 SDRAM DIMMs are supported." - "\n"); - printf("Replace the module with a DDR2 DIMM." - "\n\n"); - spd_ddr_init_hang(); - } - dimm_found = TRUE; - debug("DIMM slot %lu: populated with %lu-rank DDR2 DIMM" - "\n", dimm_num, ranks_on_dimm); - if (ranks_on_dimm > max_ranks_per_dimm) { - printf("WARNING: DRAM DIMM in slot %lu has %lu " - "ranks.\n", dimm_num, ranks_on_dimm); - if (1 == max_ranks_per_dimm) { - printf("Only one rank will be used.\n"); - } else { - printf - ("Only two ranks will be used.\n"); - } - ranks_on_dimm = max_ranks_per_dimm; - } - dimm_ranks[dimm_num] = ranks_on_dimm; - *ranks += ranks_on_dimm; - } else { - dimm_ranks[dimm_num] = 0; - debug("DIMM slot %lu: Not populated\n", dimm_num); - } - } - if (dimm_found == FALSE) { - printf("ERROR: No memory installed.\n"); - printf("Install at least one DDR2 DIMM.\n\n"); - spd_ddr_init_hang(); - } - debug("Total number of ranks = %d\n", *ranks); -} - -/*------------------------------------------------------------------ - * For the memory DIMMs installed, this routine verifies that - * frequency previously calculated is supported. - *-----------------------------------------------------------------*/ -static void check_frequency(unsigned long *dimm_ranks, - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, - unsigned long sdram_freq) -{ - unsigned long dimm_num; - unsigned long cycle_time; - unsigned long calc_cycle_time; - - /* - * calc_cycle_time is calculated from DDR frequency set by board/chip - * and is expressed in picoseconds to match the way DIMM cycle time is - * calculated below. - */ - calc_cycle_time = MULDIV64(ONE_BILLION, 1000, sdram_freq); - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_ranks[dimm_num]) { - cycle_time = - get_tcyc(spd_read(iic0_dimm_addr[dimm_num], 9)); - debug("cycle_time=%d ps\n", cycle_time); - - if (cycle_time > (calc_cycle_time + 10)) { - /* - * the provided sdram cycle_time is too small - * for the available DIMM cycle_time. The - * additionnal 10ps is here to accept a small - * incertainty. - */ - printf - ("ERROR: DRAM DIMM detected with cycle_time %d ps in " - "slot %d \n while calculated cycle time is %d ps.\n", - (unsigned int)cycle_time, - (unsigned int)dimm_num, - (unsigned int)calc_cycle_time); - printf - ("Replace the DIMM, or change DDR frequency via " - "strapping bits.\n\n"); - spd_ddr_init_hang(); - } - } - } -} - -/*------------------------------------------------------------------ - * This routine gets size information for the installed memory - * DIMMs. - *-----------------------------------------------------------------*/ -static void get_dimm_size(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, - unsigned long *const rows, - unsigned long *const banks, - unsigned long *const cols, unsigned long *const width) -{ - unsigned long dimm_num; - - *rows = 0; - *banks = 0; - *cols = 0; - *width = 0; - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_ranks[dimm_num]) { - unsigned long t; - - /* Rows */ - t = spd_read(iic0_dimm_addr[dimm_num], 3); - if (0 == *rows) { - *rows = t; - } else if (t != *rows) { - printf("ERROR: DRAM DIMM modules do not all " - "have the same number of rows.\n\n"); - spd_ddr_init_hang(); - } - /* Banks */ - t = spd_read(iic0_dimm_addr[dimm_num], 17); - if (0 == *banks) { - *banks = t; - } else if (t != *banks) { - printf("ERROR: DRAM DIMM modules do not all " - "have the same number of banks.\n\n"); - spd_ddr_init_hang(); - } - /* Columns */ - t = spd_read(iic0_dimm_addr[dimm_num], 4); - if (0 == *cols) { - *cols = t; - } else if (t != *cols) { - printf("ERROR: DRAM DIMM modules do not all " - "have the same number of columns.\n\n"); - spd_ddr_init_hang(); - } - /* Data width */ - t = spd_read(iic0_dimm_addr[dimm_num], 6); - if (0 == *width) { - *width = t; - } else if (t != *width) { - printf("ERROR: DRAM DIMM modules do not all " - "have the same data width.\n\n"); - spd_ddr_init_hang(); - } - } - } - debug("Number of rows = %d\n", *rows); - debug("Number of columns = %d\n", *cols); - debug("Number of banks = %d\n", *banks); - debug("Data width = %d\n", *width); - if (*rows > 14) { - printf("ERROR: DRAM DIMM modules have %lu address rows.\n", - *rows); - printf("Only modules with 14 or fewer rows are supported.\n\n"); - spd_ddr_init_hang(); - } - if (4 != *banks && 8 != *banks) { - printf("ERROR: DRAM DIMM modules have %lu banks.\n", *banks); - printf("Only modules with 4 or 8 banks are supported.\n\n"); - spd_ddr_init_hang(); - } - if (*cols > 12) { - printf("ERROR: DRAM DIMM modules have %lu address columns.\n", - *cols); - printf("Only modules with 12 or fewer columns are " - "supported.\n\n"); - spd_ddr_init_hang(); - } - if (32 != *width && 40 != *width && 64 != *width && 72 != *width) { - printf("ERROR: DRAM DIMM modules have a width of %lu bit.\n", - *width); - printf("Only modules with widths of 32, 40, 64, and 72 bits " - "are supported.\n\n"); - spd_ddr_init_hang(); - } -} - -/*------------------------------------------------------------------ - * Only 1.8V modules are supported. This routine verifies this. - *-----------------------------------------------------------------*/ -static void check_voltage_type(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks) -{ - unsigned long dimm_num; - unsigned long voltage_type; - - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - if (dimm_ranks[dimm_num]) { - voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8); - if (0x05 != voltage_type) { /* 1.8V for DDR2 */ - printf("ERROR: Slot %lu provides 1.8V for DDR2 " - "DIMMs.\n", dimm_num); - switch (voltage_type) { - case 0x00: - printf("This DIMM is 5.0 Volt/TTL.\n"); - break; - case 0x01: - printf("This DIMM is LVTTL.\n"); - break; - case 0x02: - printf("This DIMM is 1.5 Volt.\n"); - break; - case 0x03: - printf("This DIMM is 3.3 Volt/TTL.\n"); - break; - case 0x04: - printf("This DIMM is 2.5 Volt.\n"); - break; - default: - printf("This DIMM is an unknown " - "voltage.\n"); - break; - } - printf("Replace it with a 1.8V DDR2 DIMM.\n\n"); - spd_ddr_init_hang(); - } - } - } -} - -static void program_ddr0_03(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, - unsigned long sdram_freq, - unsigned long rows, unsigned long *cas_latency) -{ - unsigned long dimm_num; - unsigned long cas_index; - unsigned long cycle_2_0_clk; - unsigned long cycle_3_0_clk; - unsigned long cycle_4_0_clk; - unsigned long cycle_5_0_clk; - unsigned long max_2_0_tcyc_ps = 100; - unsigned long max_3_0_tcyc_ps = 100; - unsigned long max_4_0_tcyc_ps = 100; - unsigned long max_5_0_tcyc_ps = 100; - unsigned char cas_available = 0x3C; /* value for DDR2 */ - u32 ddr0_03 = DDR0_03_BSTLEN_ENCODE(0x2) | DDR0_03_INITAREF_ENCODE(0x2); - unsigned int const tcyc_addr[3] = { 9, 23, 25 }; - - /*------------------------------------------------------------------ - * Get the board configuration info. - *-----------------------------------------------------------------*/ - debug("sdram_freq = %d\n", sdram_freq); - - /*------------------------------------------------------------------ - * Handle the timing. We need to find the worst case timing of all - * the dimm modules installed. - *-----------------------------------------------------------------*/ - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_ranks[dimm_num]) { - unsigned char const cas_bit = - spd_read(iic0_dimm_addr[dimm_num], 18); - unsigned char cas_mask; - - cas_available &= cas_bit; - for (cas_mask = 0x80; cas_mask; cas_mask >>= 1) { - if (cas_bit & cas_mask) - break; - } - debug("cas_bit (SPD byte 18) = %02X, cas_mask = %02X\n", - cas_bit, cas_mask); - - for (cas_index = 0; cas_index < 3; - cas_mask >>= 1, cas_index++) { - unsigned long cycle_time_ps; - - if (!(cas_available & cas_mask)) { - continue; - } - cycle_time_ps = - get_tcyc(spd_read(iic0_dimm_addr[dimm_num], - tcyc_addr[cas_index])); - - debug("cas_index = %d: cycle_time_ps = %d\n", - cas_index, cycle_time_ps); - /* - * DDR2 devices use the following bitmask for CAS latency: - * Bit 7 6 5 4 3 2 1 0 - * TBD 6.0 5.0 4.0 3.0 2.0 TBD TBD - */ - switch (cas_mask) { - case 0x20: - max_5_0_tcyc_ps = - max(max_5_0_tcyc_ps, cycle_time_ps); - break; - case 0x10: - max_4_0_tcyc_ps = - max(max_4_0_tcyc_ps, cycle_time_ps); - break; - case 0x08: - max_3_0_tcyc_ps = - max(max_3_0_tcyc_ps, cycle_time_ps); - break; - case 0x04: - max_2_0_tcyc_ps = - max(max_2_0_tcyc_ps, cycle_time_ps); - break; - } - } - } - } - debug("cas_available (bit map) = 0x%02X\n", cas_available); - - /*------------------------------------------------------------------ - * Set the SDRAM mode, SDRAM_MMODE - *-----------------------------------------------------------------*/ - - /* add 10 here because of rounding problems */ - cycle_2_0_clk = MULDIV64(ONE_BILLION, 1000, max_2_0_tcyc_ps) + 10; - cycle_3_0_clk = MULDIV64(ONE_BILLION, 1000, max_3_0_tcyc_ps) + 10; - cycle_4_0_clk = MULDIV64(ONE_BILLION, 1000, max_4_0_tcyc_ps) + 10; - cycle_5_0_clk = MULDIV64(ONE_BILLION, 1000, max_5_0_tcyc_ps) + 10; - debug("cycle_2_0_clk = %d\n", cycle_2_0_clk); - debug("cycle_3_0_clk = %d\n", cycle_3_0_clk); - debug("cycle_4_0_clk = %d\n", cycle_4_0_clk); - debug("cycle_5_0_clk = %d\n", cycle_5_0_clk); - - if ((cas_available & 0x04) && (sdram_freq <= cycle_2_0_clk)) { - *cas_latency = 2; - ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x2) | - DDR0_03_CASLAT_LIN_ENCODE(0x4); - } else if ((cas_available & 0x08) && (sdram_freq <= cycle_3_0_clk)) { - *cas_latency = 3; - ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x3) | - DDR0_03_CASLAT_LIN_ENCODE(0x6); - } else if ((cas_available & 0x10) && (sdram_freq <= cycle_4_0_clk)) { - *cas_latency = 4; - ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x4) | - DDR0_03_CASLAT_LIN_ENCODE(0x8); - } else if ((cas_available & 0x20) && (sdram_freq <= cycle_5_0_clk)) { - *cas_latency = 5; - ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x5) | - DDR0_03_CASLAT_LIN_ENCODE(0xA); - } else { - printf("ERROR: Cannot find a supported CAS latency with the " - "installed DIMMs.\n"); - printf("Only DDR2 DIMMs with CAS latencies of 2.0, 3.0, 4.0, " - "and 5.0 are supported.\n"); - printf("Make sure the PLB speed is within the supported range " - "of the DIMMs.\n"); - printf("sdram_freq=%ld cycle2=%ld cycle3=%ld cycle4=%ld " - "cycle5=%ld\n\n", sdram_freq, cycle_2_0_clk, - cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk); - spd_ddr_init_hang(); - } - debug("CAS latency = %d\n", *cas_latency); - mtsdram(DDR0_03, ddr0_03); -} - -static void program_ddr0_04(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, - unsigned long sdram_freq) -{ - unsigned long dimm_num; - unsigned long t_rc_ps = 0; - unsigned long t_rrd_ps = 0; - unsigned long t_rtp_ps = 0; - unsigned long t_rc_clk; - unsigned long t_rrd_clk; - unsigned long t_rtp_clk; - - /*------------------------------------------------------------------ - * Handle the timing. We need to find the worst case timing of all - * the dimm modules installed. - *-----------------------------------------------------------------*/ - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_ranks[dimm_num]) { - unsigned long ps; - - /* tRC */ - ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 41); - switch (spd_read(iic0_dimm_addr[dimm_num], 40) >> 4) { - case 0x1: - ps += 250; - break; - case 0x2: - ps += 333; - break; - case 0x3: - ps += 500; - break; - case 0x4: - ps += 667; - break; - case 0x5: - ps += 750; - break; - } - t_rc_ps = max(t_rc_ps, ps); - /* tRRD */ - ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 28); - t_rrd_ps = max(t_rrd_ps, ps); - /* tRTP */ - ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 38); - t_rtp_ps = max(t_rtp_ps, ps); - } - } - debug("t_rc_ps = %d\n", t_rc_ps); - t_rc_clk = (MULDIV64(sdram_freq, t_rc_ps, ONE_BILLION) + 999) / 1000; - debug("t_rrd_ps = %d\n", t_rrd_ps); - t_rrd_clk = (MULDIV64(sdram_freq, t_rrd_ps, ONE_BILLION) + 999) / 1000; - debug("t_rtp_ps = %d\n", t_rtp_ps); - t_rtp_clk = (MULDIV64(sdram_freq, t_rtp_ps, ONE_BILLION) + 999) / 1000; - mtsdram(DDR0_04, DDR0_04_TRC_ENCODE(t_rc_clk) | - DDR0_04_TRRD_ENCODE(t_rrd_clk) | - DDR0_04_TRTP_ENCODE(t_rtp_clk)); -} - -static void program_ddr0_05(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, - unsigned long sdram_freq) -{ - unsigned long dimm_num; - unsigned long t_rp_ps = 0; - unsigned long t_ras_ps = 0; - unsigned long t_rp_clk; - unsigned long t_ras_clk; - u32 ddr0_05 = DDR0_05_TMRD_ENCODE(0x2) | DDR0_05_TEMRS_ENCODE(0x2); - - /*------------------------------------------------------------------ - * Handle the timing. We need to find the worst case timing of all - * the dimm modules installed. - *-----------------------------------------------------------------*/ - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_ranks[dimm_num]) { - unsigned long ps; - - /* tRP */ - ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 27); - t_rp_ps = max(t_rp_ps, ps); - /* tRAS */ - ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 30); - t_ras_ps = max(t_ras_ps, ps); - } - } - debug("t_rp_ps = %d\n", t_rp_ps); - t_rp_clk = (MULDIV64(sdram_freq, t_rp_ps, ONE_BILLION) + 999) / 1000; - debug("t_ras_ps = %d\n", t_ras_ps); - t_ras_clk = (MULDIV64(sdram_freq, t_ras_ps, ONE_BILLION) + 999) / 1000; - mtsdram(DDR0_05, ddr0_05 | DDR0_05_TRP_ENCODE(t_rp_clk) | - DDR0_05_TRAS_MIN_ENCODE(t_ras_clk)); -} - -static void program_ddr0_06(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, - unsigned long sdram_freq) -{ - unsigned long dimm_num; - unsigned char spd_40; - unsigned long t_wtr_ps = 0; - unsigned long t_rfc_ps = 0; - unsigned long t_wtr_clk; - unsigned long t_rfc_clk; - u32 ddr0_06 = - DDR0_06_WRITEINTERP_ENCODE(0x1) | DDR0_06_TDLL_ENCODE(200); - - /*------------------------------------------------------------------ - * Handle the timing. We need to find the worst case timing of all - * the dimm modules installed. - *-----------------------------------------------------------------*/ - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_ranks[dimm_num]) { - unsigned long ps; - - /* tWTR */ - ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 37); - t_wtr_ps = max(t_wtr_ps, ps); - /* tRFC */ - ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 42); - spd_40 = spd_read(iic0_dimm_addr[dimm_num], 40); - ps += 256000 * (spd_40 & 0x01); - switch ((spd_40 & 0x0E) >> 1) { - case 0x1: - ps += 250; - break; - case 0x2: - ps += 333; - break; - case 0x3: - ps += 500; - break; - case 0x4: - ps += 667; - break; - case 0x5: - ps += 750; - break; - } - t_rfc_ps = max(t_rfc_ps, ps); - } - } - debug("t_wtr_ps = %d\n", t_wtr_ps); - t_wtr_clk = (MULDIV64(sdram_freq, t_wtr_ps, ONE_BILLION) + 999) / 1000; - debug("t_rfc_ps = %d\n", t_rfc_ps); - t_rfc_clk = (MULDIV64(sdram_freq, t_rfc_ps, ONE_BILLION) + 999) / 1000; - mtsdram(DDR0_06, ddr0_06 | DDR0_06_TWTR_ENCODE(t_wtr_clk) | - DDR0_06_TRFC_ENCODE(t_rfc_clk)); -} - -static void program_ddr0_10(unsigned long dimm_ranks[], unsigned long ranks) -{ - unsigned long csmap; - - if (2 == ranks) { - /* Both chip selects in use */ - csmap = 0x03; - } else { - /* One chip select in use */ - csmap = (1 == dimm_ranks[0]) ? 0x1 : 0x2; - } - mtsdram(DDR0_10, DDR0_10_WRITE_MODEREG_ENCODE(0x0) | - DDR0_10_CS_MAP_ENCODE(csmap) | - DDR0_10_OCD_ADJUST_PUP_CS_0_ENCODE(0)); -} - -static void program_ddr0_11(unsigned long sdram_freq) -{ - unsigned long const t_xsnr_ps = 200000; /* 200 ns */ - unsigned long t_xsnr_clk; - - debug("t_xsnr_ps = %d\n", t_xsnr_ps); - t_xsnr_clk = - (MULDIV64(sdram_freq, t_xsnr_ps, ONE_BILLION) + 999) / 1000; - mtsdram(DDR0_11, DDR0_11_SREFRESH_ENCODE(0) | - DDR0_11_TXSNR_ENCODE(t_xsnr_clk) | DDR0_11_TXSR_ENCODE(200)); -} - -static void program_ddr0_22(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, unsigned long width) -{ -#if defined(CONFIG_DDR_ECC) - unsigned long dimm_num; - unsigned long ecc_available = width >= 64; - u32 ddr0_22 = DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) | - DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) | - DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS); - - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_ranks[dimm_num]) { - /* Check for ECC */ - if (0 == (spd_read(iic0_dimm_addr[dimm_num], 11) & - 0x02)) { - ecc_available = FALSE; - } - } - } - if (ecc_available) { - debug("ECC found on all DIMMs present\n"); - mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x3)); - } else { - debug("ECC not found on some or all DIMMs present\n"); - mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x0)); - } -#else - mtsdram(DDR0_22, DDR0_22_CTRL_RAW_ENCODE(0x0) | - DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) | - DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) | - DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS)); -#endif /* defined(CONFIG_DDR_ECC) */ -} - -static void program_ddr0_24(unsigned long ranks) -{ - u32 ddr0_24 = DDR0_24_RTT_PAD_TERMINATION_ENCODE(0x1) | /* 75 ohm */ - DDR0_24_ODT_RD_MAP_CS1_ENCODE(0x0); - - if (2 == ranks) { - /* Both chip selects in use */ - ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x1) | - DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x2); - } else { - /* One chip select in use */ - /* One of the two fields added to ddr0_24 is a "don't care" */ - ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x2) | - DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x1); - } - mtsdram(DDR0_24, ddr0_24); -} - -static void program_ddr0_26(unsigned long sdram_freq) -{ - unsigned long const t_ref_ps = 7800000; /* 7.8 us. refresh */ - /* TODO: check definition of tRAS_MAX */ - unsigned long const t_ras_max_ps = 9 * t_ref_ps; - unsigned long t_ras_max_clk; - unsigned long t_ref_clk; - - /* Round down t_ras_max_clk and t_ref_clk */ - debug("t_ras_max_ps = %d\n", t_ras_max_ps); - t_ras_max_clk = MULDIV64(sdram_freq, t_ras_max_ps, ONE_BILLION) / 1000; - debug("t_ref_ps = %d\n", t_ref_ps); - t_ref_clk = MULDIV64(sdram_freq, t_ref_ps, ONE_BILLION) / 1000; - mtsdram(DDR0_26, DDR0_26_TRAS_MAX_ENCODE(t_ras_max_clk) | - DDR0_26_TREF_ENCODE(t_ref_clk)); -} - -static void program_ddr0_27(unsigned long sdram_freq) -{ - unsigned long const t_init_ps = 200000000; /* 200 us. init */ - unsigned long t_init_clk; - - debug("t_init_ps = %d\n", t_init_ps); - t_init_clk = - (MULDIV64(sdram_freq, t_init_ps, ONE_BILLION) + 999) / 1000; - mtsdram(DDR0_27, DDR0_27_EMRS_DATA_ENCODE(0x0000) | - DDR0_27_TINIT_ENCODE(t_init_clk)); -} - -static void program_ddr0_43(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, - unsigned long sdram_freq, - unsigned long cols, unsigned long banks) -{ - unsigned long dimm_num; - unsigned long t_wr_ps = 0; - unsigned long t_wr_clk; - u32 ddr0_43 = DDR0_43_APREBIT_ENCODE(10) | - DDR0_43_COLUMN_SIZE_ENCODE(12 - cols) | - DDR0_43_EIGHT_BANK_MODE_ENCODE(8 == banks ? 1 : 0); - - /*------------------------------------------------------------------ - * Handle the timing. We need to find the worst case timing of all - * the dimm modules installed. - *-----------------------------------------------------------------*/ - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_ranks[dimm_num]) { - unsigned long ps; - - ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 36); - t_wr_ps = max(t_wr_ps, ps); - } - } - debug("t_wr_ps = %d\n", t_wr_ps); - t_wr_clk = (MULDIV64(sdram_freq, t_wr_ps, ONE_BILLION) + 999) / 1000; - mtsdram(DDR0_43, ddr0_43 | DDR0_43_TWR_ENCODE(t_wr_clk)); -} - -static void program_ddr0_44(unsigned long dimm_ranks[], - unsigned char const iic0_dimm_addr[], - unsigned long num_dimm_banks, - unsigned long sdram_freq) -{ - unsigned long dimm_num; - unsigned long t_rcd_ps = 0; - unsigned long t_rcd_clk; - - /*------------------------------------------------------------------ - * Handle the timing. We need to find the worst case timing of all - * the dimm modules installed. - *-----------------------------------------------------------------*/ - /* loop through all the DIMM slots on the board */ - for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { - /* If a dimm is installed in a particular slot ... */ - if (dimm_ranks[dimm_num]) { - unsigned long ps; - - ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 29); - t_rcd_ps = max(t_rcd_ps, ps); - } - } - debug("t_rcd_ps = %d\n", t_rcd_ps); - t_rcd_clk = (MULDIV64(sdram_freq, t_rcd_ps, ONE_BILLION) + 999) / 1000; - mtsdram(DDR0_44, DDR0_44_TRCD_ENCODE(t_rcd_clk)); -} - -/*-----------------------------------------------------------------------------+ - * initdram. Initializes the 440EPx/GPx DDR SDRAM controller. - * Note: This routine runs from flash with a stack set up in the chip's - * sram space. It is important that the routine does not require .sbss, .bss or - * .data sections. It also cannot call routines that require these sections. - *-----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------- - * Function: initdram - * Description: Configures SDRAM memory banks for DDR operation. - * Auto Memory Configuration option reads the DDR SDRAM EEPROMs - * via the IIC bus and then configures the DDR SDRAM memory - * banks appropriately. If Auto Memory Configuration is - * not used, it is assumed that no DIMM is plugged - *-----------------------------------------------------------------------------*/ -phys_size_t initdram(int board_type) -{ - unsigned char const iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; - unsigned long dimm_ranks[MAXDIMMS]; - unsigned long ranks; - unsigned long rows; - unsigned long banks; - unsigned long cols; - unsigned long width; - unsigned long const sdram_freq = get_bus_freq(0); - unsigned long const num_dimm_banks = sizeof(iic0_dimm_addr); /* on board dimm banks */ - unsigned long cas_latency = 0; /* to quiet initialization warning */ - unsigned long dram_size; - - debug("\nEntering initdram()\n"); - - /*------------------------------------------------------------------ - * Stop the DDR-SDRAM controller. - *-----------------------------------------------------------------*/ - mtsdram(DDR0_02, DDR0_02_START_ENCODE(0)); - - /* - * Make sure I2C controller is initialized - * before continuing. - */ - /* switch to correct I2C bus */ - I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM); - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - - /*------------------------------------------------------------------ - * Clear out the serial presence detect buffers. - * Perform IIC reads from the dimm. Fill in the spds. - * Check to see if the dimm slots are populated - *-----------------------------------------------------------------*/ - get_spd_info(dimm_ranks, &ranks, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Check the frequency supported for the dimms plugged. - *-----------------------------------------------------------------*/ - check_frequency(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); - - /*------------------------------------------------------------------ - * Check and get size information. - *-----------------------------------------------------------------*/ - get_dimm_size(dimm_ranks, iic0_dimm_addr, num_dimm_banks, &rows, &banks, - &cols, &width); - - /*------------------------------------------------------------------ - * Check the voltage type for the dimms plugged. - *-----------------------------------------------------------------*/ - check_voltage_type(dimm_ranks, iic0_dimm_addr, num_dimm_banks); - - /*------------------------------------------------------------------ - * Program registers for SDRAM controller. - *-----------------------------------------------------------------*/ - mtsdram(DDR0_00, DDR0_00_DLL_INCREMENT_ENCODE(0x19) | - DDR0_00_DLL_START_POINT_DECODE(0x0A)); - - mtsdram(DDR0_01, DDR0_01_PLB0_DB_CS_LOWER_ENCODE(0x01) | - DDR0_01_PLB0_DB_CS_UPPER_ENCODE(0x00) | - DDR0_01_INT_MASK_ENCODE(0xFF)); - - program_ddr0_03(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, - rows, &cas_latency); - - program_ddr0_04(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); - - program_ddr0_05(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); - - program_ddr0_06(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); - - /* - * TODO: tFAW not found in SPD. Value of 13 taken from Sequoia - * board SDRAM, but may be overly conservative. - */ - mtsdram(DDR0_07, DDR0_07_NO_CMD_INIT_ENCODE(0) | - DDR0_07_TFAW_ENCODE(13) | - DDR0_07_AUTO_REFRESH_MODE_ENCODE(1) | - DDR0_07_AREFRESH_ENCODE(0)); - - mtsdram(DDR0_08, DDR0_08_WRLAT_ENCODE(cas_latency - 1) | - DDR0_08_TCPD_ENCODE(200) | DDR0_08_DQS_N_EN_ENCODE(0) | - DDR0_08_DDRII_ENCODE(1)); - - mtsdram(DDR0_09, DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(0x00) | - DDR0_09_RTT_0_ENCODE(0x1) | - DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(0x1D) | - DDR0_09_WR_DQS_SHIFT_ENCODE(DQS_OUT_SHIFT - 0x20)); - - program_ddr0_10(dimm_ranks, ranks); - - program_ddr0_11(sdram_freq); - - mtsdram(DDR0_12, DDR0_12_TCKE_ENCODE(3)); - - mtsdram(DDR0_14, DDR0_14_DLL_BYPASS_MODE_ENCODE(0) | - DDR0_14_REDUC_ENCODE(width <= 40 ? 1 : 0) | - DDR0_14_REG_DIMM_ENABLE_ENCODE(0)); - - mtsdram(DDR0_17, DDR0_17_DLL_DQS_DELAY_0_ENCODE(DLL_DQS_DELAY)); - - mtsdram(DDR0_18, DDR0_18_DLL_DQS_DELAY_4_ENCODE(DLL_DQS_DELAY) | - DDR0_18_DLL_DQS_DELAY_3_ENCODE(DLL_DQS_DELAY) | - DDR0_18_DLL_DQS_DELAY_2_ENCODE(DLL_DQS_DELAY) | - DDR0_18_DLL_DQS_DELAY_1_ENCODE(DLL_DQS_DELAY)); - - mtsdram(DDR0_19, DDR0_19_DLL_DQS_DELAY_8_ENCODE(DLL_DQS_DELAY) | - DDR0_19_DLL_DQS_DELAY_7_ENCODE(DLL_DQS_DELAY) | - DDR0_19_DLL_DQS_DELAY_6_ENCODE(DLL_DQS_DELAY) | - DDR0_19_DLL_DQS_DELAY_5_ENCODE(DLL_DQS_DELAY)); - - mtsdram(DDR0_20, DDR0_20_DLL_DQS_BYPASS_3_ENCODE(DLL_DQS_BYPASS) | - DDR0_20_DLL_DQS_BYPASS_2_ENCODE(DLL_DQS_BYPASS) | - DDR0_20_DLL_DQS_BYPASS_1_ENCODE(DLL_DQS_BYPASS) | - DDR0_20_DLL_DQS_BYPASS_0_ENCODE(DLL_DQS_BYPASS)); - - mtsdram(DDR0_21, DDR0_21_DLL_DQS_BYPASS_7_ENCODE(DLL_DQS_BYPASS) | - DDR0_21_DLL_DQS_BYPASS_6_ENCODE(DLL_DQS_BYPASS) | - DDR0_21_DLL_DQS_BYPASS_5_ENCODE(DLL_DQS_BYPASS) | - DDR0_21_DLL_DQS_BYPASS_4_ENCODE(DLL_DQS_BYPASS)); - - program_ddr0_22(dimm_ranks, iic0_dimm_addr, num_dimm_banks, width); - - mtsdram(DDR0_23, DDR0_23_ODT_RD_MAP_CS0_ENCODE(0x0) | - DDR0_23_FWC_ENCODE(0)); - - program_ddr0_24(ranks); - - program_ddr0_26(sdram_freq); - - program_ddr0_27(sdram_freq); - - mtsdram(DDR0_28, DDR0_28_EMRS3_DATA_ENCODE(0x0000) | - DDR0_28_EMRS2_DATA_ENCODE(0x0000)); - - mtsdram(DDR0_31, DDR0_31_XOR_CHECK_BITS_ENCODE(0x0000)); - - mtsdram(DDR0_42, DDR0_42_ADDR_PINS_ENCODE(14 - rows) | - DDR0_42_CASLAT_LIN_GATE_ENCODE(2 * cas_latency)); - - program_ddr0_43(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, - cols, banks); - - program_ddr0_44(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); - - denali_sdram_register_dump(); - - dram_size = (width >= 64) ? 8 : 4; - dram_size *= 1 << cols; - dram_size *= banks; - dram_size *= 1 << rows; - dram_size *= ranks; - debug("dram_size = %lu\n", dram_size); - - /* Start the SDRAM controler */ - mtsdram(DDR0_02, DDR0_02_START_ENCODE(1)); - denali_wait_for_dlllock(); - -#if defined(CONFIG_DDR_DATA_EYE) - /* - * Map the first 1 MiB of memory in the TLB, and perform the data eye - * search. - */ - program_tlb(0, CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE, TLB_WORD2_I_ENABLE); - denali_core_search_data_eye(); - denali_sdram_register_dump(); - remove_tlb(CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE); -#endif - -#if defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) - program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, 0); - sync(); - /* Zero the memory */ - debug("Zeroing SDRAM..."); -#if defined(CONFIG_SYS_MEM_TOP_HIDE) - dcbz_area(CONFIG_SYS_SDRAM_BASE, dram_size - CONFIG_SYS_MEM_TOP_HIDE); -#else -#error Please define CONFIG_SYS_MEM_TOP_HIDE (see README) in your board config file -#endif - /* Write modified dcache lines back to memory */ - clean_dcache_range(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_BASE + dram_size - CONFIG_SYS_MEM_TOP_HIDE); - debug("Completed\n"); - sync(); - remove_tlb(CONFIG_SYS_SDRAM_BASE, dram_size); - -#if defined(CONFIG_DDR_ECC) - /* - * If ECC is enabled, clear and enable interrupts - */ - if (is_ecc_enabled()) { - u32 val; - - sync(); - /* Clear error status */ - mfsdram(DDR0_00, val); - mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); - /* Set 'int_mask' parameter to functionnal value */ - mfsdram(DDR0_01, val); - mtsdram(DDR0_01, (val & ~DDR0_01_INT_MASK_MASK) | - DDR0_01_INT_MASK_ALL_OFF); -#if defined(CONFIG_DDR_DATA_EYE) - /* - * Running denali_core_search_data_eye() when ECC is enabled - * causes non-ECC machine checks. This clears them. - */ - print_mcsr(); - mtspr(SPRN_MCSR, mfspr(SPRN_MCSR)); - print_mcsr(); -#endif - sync(); - } -#endif /* defined(CONFIG_DDR_ECC) */ -#endif /* defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) */ - - program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, MY_TLB_WORD2_I_ENABLE); - return dram_size; -} - -void board_add_ram_info(int use_default) -{ - u32 val; - - printf(" (ECC"); - if (!is_ecc_enabled()) { - printf(" not"); - } - printf(" enabled, %ld MHz", (2 * get_bus_freq(0)) / 1000000); - - mfsdram(DDR0_03, val); - printf(", CL%d)", DDR0_03_CASLAT_LIN_DECODE(val) >> 1); -} -#endif /* CONFIG_SPD_EEPROM */ diff --git a/arch/powerpc/cpu/ppc4xx/ecc.c b/arch/powerpc/cpu/ppc4xx/ecc.c deleted file mode 100644 index 7fe5dbb..0000000 --- a/arch/powerpc/cpu/ppc4xx/ecc.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2008 Nuovation System Designs, LLC - * Grant Erickson <gerickson@nuovations.com> - * - * (C) Copyright 2005-2009 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * (C) Copyright 2002 - * Jun Gu, Artesyn Technology, jung@artesyncp.com - * - * (C) Copyright 2001 - * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will abe 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 - * - * Description: - * This file implements generic DRAM ECC initialization for - * PowerPC processors using a SDRAM DDR/DDR2 controller, - * including the 405EX(r), 440GP/GX/EP/GR, 440SP(E), and - * 460EX/GT. - */ - -#include <common.h> -#include <asm/ppc4xx.h> -#include <ppc_asm.tmpl> -#include <ppc_defs.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <asm/mmu.h> -#include <asm/cache.h> - -#include "ecc.h" - -#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \ - defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) -#if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) - -#if defined(CONFIG_405EX) -/* - * Currently only 405EX uses 16bit data bus width as an alternative - * option to 32bit data width (SDRAM0_MCOPT1_WDTH) - */ -#define SDRAM_DATA_ALT_WIDTH 2 -#else -#define SDRAM_DATA_ALT_WIDTH 8 -#endif - -static void wait_ddr_idle(void) -{ - u32 val; - - do { - mfsdram(SDRAM_MCSTAT, val); - } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT); -} - -static void program_ecc_addr(unsigned long start_address, - unsigned long num_bytes, - unsigned long tlb_word2_i_value) -{ - unsigned long current_address; - unsigned long end_address; - unsigned long address_increment; - unsigned long mcopt1; - char str[] = "ECC generation -"; - char slash[] = "\\|/-\\|/-"; - int loop = 0; - int loopi = 0; - - current_address = start_address; - mfsdram(SDRAM_MCOPT1, mcopt1); - if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) { - mtsdram(SDRAM_MCOPT1, - (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN); - sync(); - eieio(); - wait_ddr_idle(); - - puts(str); - -#ifdef CONFIG_440 - if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) { -#endif - /* ECC bit set method for non-cached memory */ - if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32) - address_increment = 4; - else - address_increment = SDRAM_DATA_ALT_WIDTH; - end_address = current_address + num_bytes; - - while (current_address < end_address) { - *((unsigned long *)current_address) = 0; - current_address += address_increment; - - if ((loop++ % (2 << 20)) == 0) { - putc('\b'); - putc(slash[loopi++ % 8]); - } - } -#ifdef CONFIG_440 - } else { - /* ECC bit set method for cached memory */ - dcbz_area(start_address, num_bytes); - /* Write modified dcache lines back to memory */ - clean_dcache_range(start_address, start_address + num_bytes); - } -#endif /* CONFIG_440 */ - - blank_string(strlen(str)); - - sync(); - eieio(); - wait_ddr_idle(); - - /* clear ECC error repoting registers */ - mtsdram(SDRAM_ECCES, 0xffffffff); -#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) - /* - * IBM DDR(1) core (440GX): - * Clear Mx bits in SDRAM0_BESR0/1 - */ - mtsdram(SDRAM0_BESR0, 0xffffffff); - mtsdram(SDRAM0_BESR1, 0xffffffff); -#elif defined(CONFIG_440) - /* - * 440/460 DDR2 core: - * Clear EMID (Error PLB Master ID) in MQ0_ESL - */ - mtdcr(SDRAM_ERRSTATLL, 0xfff00000); -#else - /* - * 405EX(r) DDR2 core: - * Clear M0ID (Error PLB Master ID) in SDRAM_BESR - */ - mtsdram(SDRAM_BESR, 0xf0000000); -#endif - - mtsdram(SDRAM_MCOPT1, - (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP); - sync(); - eieio(); - wait_ddr_idle(); - } -} - -#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) -void ecc_init(unsigned long * const start, unsigned long size) -{ - /* - * Init ECC with cache disabled (on PPC's with IBM DDR - * controller (non DDR2), not tested with cache enabled yet - */ - program_ecc_addr((u32)start, size, TLB_WORD2_I_ENABLE); -} -#endif - -#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) -void do_program_ecc(unsigned long tlb_word2_i_value) -{ - unsigned long mcopt1; - unsigned long mcopt2; - unsigned long mcstat; - phys_size_t memsize = sdram_memsize(); - - if (memsize > CONFIG_MAX_MEM_MAPPED) { - printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n"); - return; - } - - mfsdram(SDRAM_MCOPT1, mcopt1); - mfsdram(SDRAM_MCOPT2, mcopt2); - - if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) { - /* DDR controller must be enabled and not in self-refresh. */ - mfsdram(SDRAM_MCSTAT, mcstat); - if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE) - && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT) - && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK)) - == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) { - - program_ecc_addr(0, memsize, tlb_word2_i_value); - } - } -} -#endif - -#endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */ -#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */ diff --git a/arch/powerpc/cpu/ppc4xx/ecc.h b/arch/powerpc/cpu/ppc4xx/ecc.h deleted file mode 100644 index b258891..0000000 --- a/arch/powerpc/cpu/ppc4xx/ecc.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2008 Nuovation System Designs, LLC - * Grant Erickson <gerickson@nuovations.com> - * - * Copyright (c) 2007-2009 DENX Software Engineering, GmbH - * Stefan Roese <sr@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 abe 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 - * - * Description: - * This file implements ECC initialization for PowerPC processors - * using the IBM SDRAM DDR1 & DDR2 controller. - * - */ - -#ifndef _ECC_H_ -#define _ECC_H_ - -/* - * Since the IBM DDR controller used on 440GP/GX/EP/GR is not register - * compatible to the IBM DDR/2 controller used on 405EX/440SP/SPe/460EX/GT - * we need to make some processor dependant defines used later on by the - * driver. - */ - -/* For 440GP/GX/EP/GR */ -#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) -#define SDRAM_MCOPT1 SDRAM_CFG0 -#define SDRAM_MCOPT1_MCHK_MASK SDRAM_CFG0_MCHK_MASK -#define SDRAM_MCOPT1_MCHK_NON SDRAM_CFG0_MCHK_NON -#define SDRAM_MCOPT1_MCHK_GEN SDRAM_CFG0_MCHK_GEN -#define SDRAM_MCOPT1_MCHK_CHK SDRAM_CFG0_MCHK_CHK -#define SDRAM_MCOPT1_MCHK_CHK_REP SDRAM_CFG0_MCHK_CHK -#define SDRAM_MCOPT1_DMWD_MASK SDRAM_CFG0_DMWD_MASK -#define SDRAM_MCOPT1_DMWD_32 SDRAM_CFG0_DMWD_32 - -#define SDRAM_MCSTAT SDRAM0_MCSTS -#define SDRAM_MCSTAT_IDLE_MASK SDRAM_MCSTS_CIS -#define SDRAM_MCSTAT_IDLE_NOT SDRAM_MCSTS_IDLE_NOT - -#define SDRAM_ECCES SDRAM0_ECCESR -#endif - -void ecc_init(unsigned long * const start, unsigned long size); -void do_program_ecc(unsigned long tlb_word2_i_value); - -static void inline blank_string(int size) -{ - int i; - - for (i = 0; i < size; i++) - putc('\b'); - for (i = 0; i < size; i++) - putc(' '); - for (i = 0; i < size; i++) - putc('\b'); -} - -#endif /* _ECC_H_ */ diff --git a/arch/powerpc/cpu/ppc4xx/fdt.c b/arch/powerpc/cpu/ppc4xx/fdt.c deleted file mode 100644 index 5ddb880..0000000 --- a/arch/powerpc/cpu/ppc4xx/fdt.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * (C) Copyright 2007-2008 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <watchdog.h> -#include <command.h> -#include <asm/cache.h> -#include <asm/ppc4xx.h> - -#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) -#include <libfdt.h> -#include <libfdt_env.h> -#include <fdt_support.h> -#include <asm/4xx_pcie.h> - -DECLARE_GLOBAL_DATA_PTR; - -void __ft_board_setup(void *blob, bd_t *bd) -{ - int rc; - int i; - u32 bxcr; - u32 ranges[EBC_NUM_BANKS * 4]; - u32 *p = ranges; - char ebc_path[] = "/plb/opb/ebc"; - - ft_cpu_setup(blob, bd); - - /* - * Read 4xx EBC bus bridge registers to get mappings of the - * peripheral banks into the OPB/PLB address space - */ - for (i = 0; i < EBC_NUM_BANKS; i++) { - mtdcr(EBC0_CFGADDR, EBC_BXCR(i)); - bxcr = mfdcr(EBC0_CFGDATA); - - if ((bxcr & EBC_BXCR_BU_MASK) != EBC_BXCR_BU_NONE) { - *p++ = i; - *p++ = 0; - *p++ = bxcr & EBC_BXCR_BAS_MASK; - *p++ = EBC_BXCR_BANK_SIZE(bxcr); - } - } - - -#ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE - /* Update reg property in all nor flash nodes too */ - fdt_fixup_nor_flash_size(blob); -#endif - - /* Some 405 PPC's have EBC as direct PLB child in the dts */ - if (fdt_path_offset(blob, ebc_path) < 0) - strcpy(ebc_path, "/plb/ebc"); - rc = fdt_find_and_setprop(blob, ebc_path, "ranges", ranges, - (p - ranges) * sizeof(u32), 1); - if (rc) { - printf("Unable to update property EBC mappings, err=%s\n", - fdt_strerror(rc)); - } -} -void ft_board_setup(void *blob, bd_t *bd) __attribute__((weak, alias("__ft_board_setup"))); - -/* - * Fixup all PCIe nodes by setting the device_type property - * to "pci-endpoint" instead is "pci" for endpoint ports. - * This property will get checked later by the Linux driver - * to properly configure the PCIe port in Linux (again). - */ -void fdt_pcie_setup(void *blob) -{ - const char *compat = "ibm,plb-pciex"; - const char *prop = "device_type"; - const char *prop_val = "pci-endpoint"; - const u32 *port; - int no; - int rc; - - /* Search first PCIe node */ - no = fdt_node_offset_by_compatible(blob, -1, compat); - while (no != -FDT_ERR_NOTFOUND) { - port = fdt_getprop(blob, no, "port", NULL); - if (port == NULL) { - printf("WARNING: could not find port property\n"); - } else { - if (is_end_point(*port)) { - rc = fdt_setprop(blob, no, prop, prop_val, - strlen(prop_val) + 1); - if (rc < 0) - printf("WARNING: could not set %s for %s: %s.\n", - prop, compat, fdt_strerror(rc)); - } - } - - /* Jump to next PCIe node */ - no = fdt_node_offset_by_compatible(blob, no, compat); - } -} - -void ft_cpu_setup(void *blob, bd_t *bd) -{ - sys_info_t sys_info; - int off, ndepth = 0; - - get_sys_info(&sys_info); - - do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "timebase-frequency", - bd->bi_intfreq, 1); - do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "clock-frequency", - bd->bi_intfreq, 1); - do_fixup_by_path_u32(blob, "/plb", "clock-frequency", sys_info.freqPLB, 1); - do_fixup_by_path_u32(blob, "/plb/opb", "clock-frequency", sys_info.freqOPB, 1); - - if (fdt_path_offset(blob, "/plb/opb/ebc") >= 0) - do_fixup_by_path_u32(blob, "/plb/opb/ebc", "clock-frequency", - sys_info.freqEBC, 1); - else - do_fixup_by_path_u32(blob, "/plb/ebc", "clock-frequency", - sys_info.freqEBC, 1); - - fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); - - /* - * Fixup all UART clocks for CPU internal UARTs - * (only these UARTs are definitely clocked by gd->uart_clk) - * - * These UARTs are direct childs of /plb/opb. This code - * does not touch any UARTs that are connected to the ebc. - */ - off = fdt_path_offset(blob, "/plb/opb"); - while ((off = fdt_next_node(blob, off, &ndepth)) >= 0) { - /* - * process all sub nodes and stop when we are back - * at the starting depth - */ - if (ndepth <= 0) - break; - - /* only update direct childs */ - if ((ndepth == 1) && - (fdt_node_check_compatible(blob, off, "ns16550") == 0)) - fdt_setprop(blob, off, - "clock-frequency", - (void*)&(gd->uart_clk), 4); - } - - /* - * Fixup all ethernet nodes - * Note: aliases in the dts are required for this - */ - fdt_fixup_ethernet(blob); - - /* - * Fixup all available PCIe nodes by setting the device_type property - */ - fdt_pcie_setup(blob); -} -#endif /* CONFIG_OF_LIBFDT && CONFIG_OF_BOARD_SETUP */ diff --git a/arch/powerpc/cpu/ppc4xx/gpio.c b/arch/powerpc/cpu/ppc4xx/gpio.c deleted file mode 100644 index 20f0572..0000000 --- a/arch/powerpc/cpu/ppc4xx/gpio.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * (C) Copyright 2007-2008 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <asm/ppc4xx-gpio.h> - -/* Only compile this file for boards with GPIO support */ -#if defined(GPIO0_BASE) - -#if defined(CONFIG_SYS_4xx_GPIO_TABLE) -gpio_param_s const gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CONFIG_SYS_4xx_GPIO_TABLE; -#endif - -#if defined(GPIO0_OSRL) -/* Only some 4xx variants support alternate funtions on the GPIO's */ -void gpio_config(int pin, int in_out, int gpio_alt, int out_val) -{ - u32 mask; - u32 mask2; - u32 val; - u32 offs = 0; - u32 offs2 = 0; - int pin2 = pin << 1; - - if (pin >= GPIO_MAX) { - offs = 0x100; - pin -= GPIO_MAX; - } - - if (pin >= GPIO_MAX/2) { - offs2 = 0x4; - pin2 = (pin - GPIO_MAX/2) << 1; - } - - mask = 0x80000000 >> pin; - mask2 = 0xc0000000 >> pin2; - - /* first set TCR to 0 */ - out_be32((void *)GPIO0_TCR + offs, in_be32((void *)GPIO0_TCR + offs) & ~mask); - - if (in_out == GPIO_OUT) { - val = in_be32((void *)GPIO0_OSRL + offs + offs2) & ~mask2; - switch (gpio_alt) { - case GPIO_ALT1: - val |= GPIO_ALT1_SEL >> pin2; - break; - case GPIO_ALT2: - val |= GPIO_ALT2_SEL >> pin2; - break; - case GPIO_ALT3: - val |= GPIO_ALT3_SEL >> pin2; - break; - } - out_be32((void *)GPIO0_OSRL + offs + offs2, val); - - /* setup requested output value */ - if (out_val == GPIO_OUT_0) - out_be32((void *)GPIO0_OR + offs, - in_be32((void *)GPIO0_OR + offs) & ~mask); - else if (out_val == GPIO_OUT_1) - out_be32((void *)GPIO0_OR + offs, - in_be32((void *)GPIO0_OR + offs) | mask); - - /* now configure TCR to drive output if selected */ - out_be32((void *)GPIO0_TCR + offs, - in_be32((void *)GPIO0_TCR + offs) | mask); - } else { - val = in_be32((void *)GPIO0_ISR1L + offs + offs2) & ~mask2; - val |= GPIO_IN_SEL >> pin2; - out_be32((void *)GPIO0_ISR1L + offs + offs2, val); - } -} -#endif /* GPIO_OSRL */ - -void gpio_write_bit(int pin, int val) -{ - u32 offs = 0; - - if (pin >= GPIO_MAX) { - offs = 0x100; - pin -= GPIO_MAX; - } - - if (val) - out_be32((void *)GPIO0_OR + offs, - in_be32((void *)GPIO0_OR + offs) | GPIO_VAL(pin)); - else - out_be32((void *)GPIO0_OR + offs, - in_be32((void *)GPIO0_OR + offs) & ~GPIO_VAL(pin)); -} - -int gpio_read_out_bit(int pin) -{ - u32 offs = 0; - - if (pin >= GPIO_MAX) { - offs = 0x100; - pin -= GPIO_MAX; - } - - return (in_be32((void *)GPIO0_OR + offs) & GPIO_VAL(pin) ? 1 : 0); -} - -int gpio_read_in_bit(int pin) -{ - u32 offs = 0; - - if (pin >= GPIO_MAX) { - offs = 0x100; - pin -= GPIO_MAX; - } - - return (in_be32((void *)GPIO0_IR + offs) & GPIO_VAL(pin) ? 1 : 0); -} - -#if defined(CONFIG_SYS_4xx_GPIO_TABLE) -void gpio_set_chip_configuration(void) -{ - unsigned char i=0, j=0, offs=0, gpio_core; - unsigned long reg, core_add; - - for (gpio_core=0; gpio_core<GPIO_GROUP_MAX; gpio_core++) { - j = 0; - offs = 0; - /* GPIO config of the GPIOs 0 to 31 */ - for (i=0; i<GPIO_MAX; i++, j++) { - if (i == GPIO_MAX/2) { - offs = 4; - j = i-16; - } - - core_add = gpio_tab[gpio_core][i].add; - - if ((gpio_tab[gpio_core][i].in_out == GPIO_IN) || - (gpio_tab[gpio_core][i].in_out == GPIO_BI)) { - - switch (gpio_tab[gpio_core][i].alt_nb) { - case GPIO_SEL: - break; - - case GPIO_ALT1: - reg = in_be32((void *)GPIO_IS1(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_IN_SEL >> (j*2)); - out_be32((void *)GPIO_IS1(core_add+offs), reg); - break; - - case GPIO_ALT2: - reg = in_be32((void *)GPIO_IS2(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_IN_SEL >> (j*2)); - out_be32((void *)GPIO_IS2(core_add+offs), reg); - break; - - case GPIO_ALT3: - reg = in_be32((void *)GPIO_IS3(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_IN_SEL >> (j*2)); - out_be32((void *)GPIO_IS3(core_add+offs), reg); - break; - } - } - - if ((gpio_tab[gpio_core][i].in_out == GPIO_OUT) || - (gpio_tab[gpio_core][i].in_out == GPIO_BI)) { - - u32 gpio_alt_sel = 0; - - switch (gpio_tab[gpio_core][i].alt_nb) { - case GPIO_SEL: - /* - * Setup output value - * 1 -> high level - * 0 -> low level - * else -> don't touch - */ - reg = in_be32((void *)GPIO_OR(core_add)); - if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) - reg |= (0x80000000 >> (i)); - else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0) - reg &= ~(0x80000000 >> (i)); - out_be32((void *)GPIO_OR(core_add), reg); - - reg = in_be32((void *)GPIO_TCR(core_add)) | - (0x80000000 >> (i)); - out_be32((void *)GPIO_TCR(core_add), reg); - - reg = in_be32((void *)GPIO_OS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - out_be32((void *)GPIO_OS(core_add+offs), reg); - reg = in_be32((void *)GPIO_TS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - out_be32((void *)GPIO_TS(core_add+offs), reg); - break; - - case GPIO_ALT1: - gpio_alt_sel = GPIO_ALT1_SEL; - break; - - case GPIO_ALT2: - gpio_alt_sel = GPIO_ALT2_SEL; - break; - - case GPIO_ALT3: - gpio_alt_sel = GPIO_ALT3_SEL; - break; - } - - if (0 != gpio_alt_sel) { - reg = in_be32((void *)GPIO_OS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (gpio_alt_sel >> (j*2)); - out_be32((void *)GPIO_OS(core_add+offs), reg); - - if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) { - reg = in_be32((void *)GPIO_TCR(core_add)) - | (0x80000000 >> (i)); - out_be32((void *)GPIO_TCR(core_add), reg); - reg = in_be32((void *)GPIO_TS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - out_be32((void *)GPIO_TS(core_add+offs), reg); - } else { - reg = in_be32((void *)GPIO_TCR(core_add)) - & ~(0x80000000 >> (i)); - out_be32((void *)GPIO_TCR(core_add), reg); - reg = in_be32((void *)GPIO_TS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (gpio_alt_sel >> (j*2)); - out_be32((void *)GPIO_TS(core_add+offs), reg); - } - } - } - } - } -} - -#endif /* GPIO0_BASE */ -#endif /* CONFIG_SYS_4xx_GPIO_TABLE */ diff --git a/arch/powerpc/cpu/ppc4xx/interrupts.c b/arch/powerpc/cpu/ppc4xx/interrupts.c deleted file mode 100644 index d0bca92..0000000 --- a/arch/powerpc/cpu/ppc4xx/interrupts.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * (C) Copyright 2000-2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2002 (440 port) - * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com - * - * (C) Copyright 2003 (440GX port) - * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com - * - * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX) - * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es - * Work supported by Qtechnology (htpp://qtec.com) - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <watchdog.h> -#include <command.h> -#include <asm/processor.h> -#include <asm/interrupt.h> -#include <asm/ppc4xx.h> -#include <ppc_asm.tmpl> -#include <commproc.h> - -DECLARE_GLOBAL_DATA_PTR; - -/* - * CPM interrupt vector functions. - */ -struct irq_action { - interrupt_handler_t *handler; - void *arg; - int count; -}; -static struct irq_action irq_vecs[IRQ_MAX]; - -#if defined(CONFIG_440) - -/* SPRN changed in 440 */ -static __inline__ void set_evpr(unsigned long val) -{ - asm volatile("mtspr 0x03f,%0" : : "r" (val)); -} - -#else /* !defined(CONFIG_440) */ - -static __inline__ void set_pit(unsigned long val) -{ - asm volatile("mtpit %0" : : "r" (val)); -} - -static __inline__ void set_evpr(unsigned long val) -{ - asm volatile("mtevpr %0" : : "r" (val)); -} -#endif /* defined(CONFIG_440 */ - -int interrupt_init_cpu (unsigned *decrementer_count) -{ - int vec; - unsigned long val; - - /* decrementer is automatically reloaded */ - *decrementer_count = 0; - - /* - * Mark all irqs as free - */ - for (vec = 0; vec < IRQ_MAX; vec++) { - irq_vecs[vec].handler = NULL; - irq_vecs[vec].arg = NULL; - irq_vecs[vec].count = 0; - } - -#ifdef CONFIG_4xx - /* - * Init PIT - */ -#if defined(CONFIG_440) - val = mfspr( SPRN_TCR ); - val &= (~0x04400000); /* clear DIS & ARE */ - mtspr( SPRN_TCR, val ); - mtspr( SPRN_DEC, 0 ); /* Prevent exception after TSR clear*/ - mtspr( SPRN_DECAR, 0 ); /* clear reload */ - mtspr( SPRN_TSR, 0x08000000 ); /* clear DEC status */ - val = gd->bd->bi_intfreq/1000; /* 1 msec */ - mtspr( SPRN_DECAR, val ); /* Set auto-reload value */ - mtspr( SPRN_DEC, val ); /* Set inital val */ -#else - set_pit(gd->bd->bi_intfreq / 1000); -#endif -#endif /* CONFIG_4xx */ - -#ifdef CONFIG_ADCIOP - /* - * Init PIT - */ - set_pit(66000); -#endif - - /* - * Enable PIT - */ - val = mfspr(SPRN_TCR); - val |= 0x04400000; - mtspr(SPRN_TCR, val); - - /* - * Set EVPR to 0 - */ - set_evpr(0x00000000); - - /* - * Call uic or xilinx_irq pic_enable - */ - pic_enable(); - - return (0); -} - -void timer_interrupt_cpu(struct pt_regs *regs) -{ - /* nothing to do here */ - return; -} - -void interrupt_run_handler(int vec) -{ - irq_vecs[vec].count++; - - if (irq_vecs[vec].handler != NULL) { - /* call isr */ - (*irq_vecs[vec].handler) (irq_vecs[vec].arg); - } else { - pic_irq_disable(vec); - printf("Masking bogus interrupt vector %d\n", vec); - } - - pic_irq_ack(vec); - return; -} - -void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg) -{ - /* - * Print warning when replacing with a different irq vector - */ - if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) { - printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n", - vec, (uint) handler, (uint) irq_vecs[vec].handler); - } - irq_vecs[vec].handler = handler; - irq_vecs[vec].arg = arg; - - pic_irq_enable(vec); - return; -} - -void irq_free_handler(int vec) -{ - debug("Free interrupt for vector %d ==> %p\n", - vec, irq_vecs[vec].handler); - - pic_irq_disable(vec); - - irq_vecs[vec].handler = NULL; - irq_vecs[vec].arg = NULL; - return; -} - -#if defined(CONFIG_CMD_IRQ) -int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int vec; - - printf ("Interrupt-Information:\n"); - printf ("Nr Routine Arg Count\n"); - - for (vec = 0; vec < IRQ_MAX; vec++) { - if (irq_vecs[vec].handler != NULL) { - printf ("%02d %08lx %08lx %d\n", - vec, - (ulong)irq_vecs[vec].handler, - (ulong)irq_vecs[vec].arg, - irq_vecs[vec].count); - } - } - - return 0; -} -#endif diff --git a/arch/powerpc/cpu/ppc4xx/iop480_uart.c b/arch/powerpc/cpu/ppc4xx/iop480_uart.c deleted file mode 100644 index 0e3423f..0000000 --- a/arch/powerpc/cpu/ppc4xx/iop480_uart.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * (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 <common.h> -#include <commproc.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <watchdog.h> - -#ifdef CONFIG_SERIAL_MULTI -#include <serial.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -#ifdef CONFIG_IOP480 - -#define SPU_BASE 0x40000000 - -#define spu_LineStat_rc 0x00 /* Line Status Register (Read/Clear) */ -#define spu_LineStat_w 0x04 /* Line Status Register (Set) */ -#define spu_Handshk_rc 0x08 /* Handshake Status Register (Read/Clear) */ -#define spu_Handshk_w 0x0c /* Handshake Status Register (Set) */ -#define spu_BRateDivh 0x10 /* Baud rate divisor high */ -#define spu_BRateDivl 0x14 /* Baud rate divisor low */ -#define spu_CtlReg 0x18 /* Control Register */ -#define spu_RxCmd 0x1c /* Rx Command Register */ -#define spu_TxCmd 0x20 /* Tx Command Register */ -#define spu_RxBuff 0x24 /* Rx data buffer */ -#define spu_TxBuff 0x24 /* Tx data buffer */ - -/*-----------------------------------------------------------------------------+ - | Line Status Register. - +-----------------------------------------------------------------------------*/ -#define asyncLSRport1 0x40000000 -#define asyncLSRport1set 0x40000004 -#define asyncLSRDataReady 0x80 -#define asyncLSRFramingError 0x40 -#define asyncLSROverrunError 0x20 -#define asyncLSRParityError 0x10 -#define asyncLSRBreakInterrupt 0x08 -#define asyncLSRTxHoldEmpty 0x04 -#define asyncLSRTxShiftEmpty 0x02 - -/*-----------------------------------------------------------------------------+ - | Handshake Status Register. - +-----------------------------------------------------------------------------*/ -#define asyncHSRport1 0x40000008 -#define asyncHSRport1set 0x4000000c -#define asyncHSRDsr 0x80 -#define asyncLSRCts 0x40 - -/*-----------------------------------------------------------------------------+ - | Control Register. - +-----------------------------------------------------------------------------*/ -#define asyncCRport1 0x40000018 -#define asyncCRNormal 0x00 -#define asyncCRLoopback 0x40 -#define asyncCRAutoEcho 0x80 -#define asyncCRDtr 0x20 -#define asyncCRRts 0x10 -#define asyncCRWordLength7 0x00 -#define asyncCRWordLength8 0x08 -#define asyncCRParityDisable 0x00 -#define asyncCRParityEnable 0x04 -#define asyncCREvenParity 0x00 -#define asyncCROddParity 0x02 -#define asyncCRStopBitsOne 0x00 -#define asyncCRStopBitsTwo 0x01 -#define asyncCRDisableDtrRts 0x00 - -/*-----------------------------------------------------------------------------+ - | Receiver Command Register. - +-----------------------------------------------------------------------------*/ -#define asyncRCRport1 0x4000001c -#define asyncRCRDisable 0x00 -#define asyncRCREnable 0x80 -#define asyncRCRIntDisable 0x00 -#define asyncRCRIntEnabled 0x20 -#define asyncRCRDMACh2 0x40 -#define asyncRCRDMACh3 0x60 -#define asyncRCRErrorInt 0x10 -#define asyncRCRPauseEnable 0x08 - -/*-----------------------------------------------------------------------------+ - | Transmitter Command Register. - +-----------------------------------------------------------------------------*/ -#define asyncTCRport1 0x40000020 -#define asyncTCRDisable 0x00 -#define asyncTCREnable 0x80 -#define asyncTCRIntDisable 0x00 -#define asyncTCRIntEnabled 0x20 -#define asyncTCRDMACh2 0x40 -#define asyncTCRDMACh3 0x60 -#define asyncTCRTxEmpty 0x10 -#define asyncTCRErrorInt 0x08 -#define asyncTCRStopPause 0x04 -#define asyncTCRBreakGen 0x02 - -/*-----------------------------------------------------------------------------+ - | Miscellanies defines. - +-----------------------------------------------------------------------------*/ -#define asyncTxBufferport1 0x40000024 -#define asyncRxBufferport1 0x40000024 -#define asyncDLABLsbport1 0x40000014 -#define asyncDLABMsbport1 0x40000010 -#define asyncXOFFchar 0x13 -#define asyncXONchar 0x11 - -/* - * Minimal serial functions needed to use one of the SMC ports - * as serial console interface. - */ - -int serial_init (void) -{ - volatile char val; - unsigned short br_reg; - - br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); - - /* - * Init onboard UART - */ - out_8((u8 *)SPU_BASE + spu_LineStat_rc, 0x78); /* Clear all bits in Line Status Reg */ - out_8((u8 *)SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */ - out_8((u8 *)SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */ - out_8((u8 *)SPU_BASE + spu_CtlReg, 0x08); /* Set 8 bits, no parity and 1 stop bit */ - out_8((u8 *)SPU_BASE + spu_RxCmd, 0xb0); /* Enable Rx */ - out_8((u8 *)SPU_BASE + spu_TxCmd, 0x9c); /* Enable Tx */ - out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ - val = in_8((u8 *)SPU_BASE + spu_RxBuff); /* Dummy read, to clear receiver */ - - return (0); -} - -void serial_setbrg (void) -{ - unsigned short br_reg; - - br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); - - out_8((u8 *)SPU_BASE + spu_BRateDivl, - (br_reg & 0x00ff)); /* Set baud rate divisor... */ - out_8((u8 *)SPU_BASE + spu_BRateDivh, - ((br_reg & 0xff00) >> 8)); /* ... */ -} - -void serial_putc (const char c) -{ - if (c == '\n') - serial_putc ('\r'); - - /* load status from handshake register */ - if (in_8((u8 *)SPU_BASE + spu_Handshk_rc) != 00) - out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ - - out_8((u8 *)SPU_BASE + spu_TxBuff, c); /* Put char */ - - while ((in_8((u8 *)SPU_BASE + spu_LineStat_rc) & 04) != 04) { - if (in_8((u8 *)SPU_BASE + spu_Handshk_rc) != 00) - out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ - } -} - -void serial_puts (const char *s) -{ - while (*s) { - serial_putc (*s++); - } -} - -int serial_getc () -{ - unsigned char status = 0; - - while (1) { - status = in_8((u8 *)asyncLSRport1); - if ((status & asyncLSRDataReady) != 0x0) { - break; - } - if ((status & ( asyncLSRFramingError | - asyncLSROverrunError | - asyncLSRParityError | - asyncLSRBreakInterrupt )) != 0) { - (void) out_8((u8 *)asyncLSRport1, - asyncLSRFramingError | - asyncLSROverrunError | - asyncLSRParityError | - asyncLSRBreakInterrupt ); - } - } - return (0x000000ff & (int) in_8((u8 *)asyncRxBufferport1)); -} - -int serial_tstc () -{ - unsigned char status; - - status = in_8((u8 *)asyncLSRport1); - if ((status & asyncLSRDataReady) != 0x0) { - return (1); - } - if ((status & ( asyncLSRFramingError | - asyncLSROverrunError | - asyncLSRParityError | - asyncLSRBreakInterrupt )) != 0) { - (void) out_8((u8 *)asyncLSRport1, - asyncLSRFramingError | - asyncLSROverrunError | - asyncLSRParityError | - asyncLSRBreakInterrupt); - } - return 0; -} - -#endif /* CONFIG_IOP480 */ diff --git a/arch/powerpc/cpu/ppc4xx/kgdb.S b/arch/powerpc/cpu/ppc4xx/kgdb.S deleted file mode 100644 index 417ba62..0000000 --- a/arch/powerpc/cpu/ppc4xx/kgdb.S +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2000 Murray Jensen <Murray.Jensen@cmst.csiro.au> - * - * 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 <command.h> -#include <asm/ppc4xx.h> -#include <version.h> - -#define CONFIG_405GP 1 /* needed for Linux kernel header files */ -#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ - -#include <ppc_asm.tmpl> -#include <ppc_defs.h> - -#include <asm/cache.h> -#include <asm/mmu.h> - -#if defined(CONFIG_CMD_KGDB) - /* - * cache flushing routines for kgdb - */ - - .globl kgdb_flush_cache_all -kgdb_flush_cache_all: - /* icache */ - iccci r0,r0 /* iccci invalidates the entire I cache */ - /* dcache */ - addi r6,0,0x0000 /* clear GPR 6 */ - addi r7,r0, 128 /* do loop for # of dcache lines */ - /* NOTE: dccci invalidates both */ - mtctr r7 /* ways in the D cache */ -..dcloop: - dccci 0,r6 /* invalidate line */ - addi r6,r6, 32 /* bump to next line */ - bdnz ..dcloop - blr - - .globl kgdb_flush_cache_range -kgdb_flush_cache_range: - li r5,L1_CACHE_BYTES-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,L1_CACHE_SHIFT - beqlr - mtctr r4 - mr r6,r3 -1: dcbst 0,r3 - addi r3,r3,L1_CACHE_BYTES - bdnz 1b - sync /* wait for dcbst's to get to ram */ - mtctr r4 -2: icbi 0,r6 - addi r6,r6,L1_CACHE_BYTES - bdnz 2b - SYNC - blr - -#endif diff --git a/arch/powerpc/cpu/ppc4xx/miiphy.c b/arch/powerpc/cpu/ppc4xx/miiphy.c deleted file mode 100644 index 9f8f8fa..0000000 --- a/arch/powerpc/cpu/ppc4xx/miiphy.c +++ /dev/null @@ -1,366 +0,0 @@ -/*-----------------------------------------------------------------------------+ - | 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 - +-----------------------------------------------------------------------------*/ -/*-----------------------------------------------------------------------------+ - | - | File Name: miiphy.c - | - | Function: This module has utilities for accessing the MII PHY through - | the EMAC3 macro. - | - | Author: Mark Wisner - | - +-----------------------------------------------------------------------------*/ - -/* define DEBUG for debugging output (obviously ;-)) */ -#if 0 -#define DEBUG -#endif - -#include <common.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <ppc_asm.tmpl> -#include <commproc.h> -#include <asm/ppc4xx-emac.h> -#include <asm/ppc4xx-mal.h> -#include <miiphy.h> - -#if !defined(CONFIG_PHY_CLK_FREQ) -#define CONFIG_PHY_CLK_FREQ 0 -#endif - -/***********************************************************/ -/* Dump out to the screen PHY regs */ -/***********************************************************/ - -void miiphy_dump (char *devname, unsigned char addr) -{ - unsigned long i; - unsigned short data; - - for (i = 0; i < 0x1A; i++) { - if (miiphy_read (devname, addr, i, &data)) { - printf ("read error for reg %lx\n", i); - return; - } - printf ("Phy reg %lx ==> %4x\n", i, data); - - /* jump to the next set of regs */ - if (i == 0x07) - i = 0x0f; - - } /* end for loop */ -} /* end dump */ - -/***********************************************************/ -/* (Re)start autonegotiation */ -/***********************************************************/ -int phy_setup_aneg (char *devname, unsigned char addr) -{ - u16 bmcr; - -#if defined(CONFIG_PHY_DYNAMIC_ANEG) - /* - * Set up advertisement based on capablilities reported by the PHY. - * This should work for both copper and fiber. - */ - u16 bmsr; -#if defined(CONFIG_PHY_GIGE) - u16 exsr = 0x0000; -#endif - - miiphy_read (devname, addr, MII_BMSR, &bmsr); - -#if defined(CONFIG_PHY_GIGE) - if (bmsr & BMSR_ESTATEN) - miiphy_read (devname, addr, MII_ESTATUS, &exsr); - - if (exsr & (ESTATUS_1000XF | ESTATUS_1000XH)) { - /* 1000BASE-X */ - u16 anar = 0x0000; - - if (exsr & ESTATUS_1000XF) - anar |= ADVERTISE_1000XFULL; - - if (exsr & ESTATUS_1000XH) - anar |= ADVERTISE_1000XHALF; - - miiphy_write (devname, addr, MII_ADVERTISE, anar); - } else -#endif - { - u16 anar, btcr; - - miiphy_read (devname, addr, MII_ADVERTISE, &anar); - anar &= ~(0x5000 | LPA_100BASE4 | LPA_100FULL | - LPA_100HALF | LPA_10FULL | LPA_10HALF); - - miiphy_read (devname, addr, MII_CTRL1000, &btcr); - btcr &= ~(0x00FF | PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD); - - if (bmsr & BMSR_100BASE4) - anar |= LPA_100BASE4; - - if (bmsr & BMSR_100FULL) - anar |= LPA_100FULL; - - if (bmsr & BMSR_100HALF) - anar |= LPA_100HALF; - - if (bmsr & BMSR_10FULL) - anar |= LPA_10FULL; - - if (bmsr & BMSR_10HALF) - anar |= LPA_10HALF; - - miiphy_write (devname, addr, MII_ADVERTISE, anar); - -#if defined(CONFIG_PHY_GIGE) - if (exsr & ESTATUS_1000_TFULL) - btcr |= PHY_1000BTCR_1000FD; - - if (exsr & ESTATUS_1000_THALF) - btcr |= PHY_1000BTCR_1000HD; - - miiphy_write (devname, addr, MII_CTRL1000, btcr); -#endif - } - -#else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */ - /* - * Set up standard advertisement - */ - u16 adv; - - miiphy_read (devname, addr, MII_ADVERTISE, &adv); - adv |= (LPA_LPACK | LPA_100FULL | LPA_100HALF | - LPA_10FULL | LPA_10HALF); - miiphy_write (devname, addr, MII_ADVERTISE, adv); - - miiphy_read (devname, addr, MII_CTRL1000, &adv); - adv |= (0x0300); - miiphy_write (devname, addr, MII_CTRL1000, adv); - -#endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */ - - /* Start/Restart aneg */ - miiphy_read (devname, addr, MII_BMCR, &bmcr); - bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); - miiphy_write (devname, addr, MII_BMCR, bmcr); - - return 0; -} - -/***********************************************************/ -/* read a phy reg and return the value with a rc */ -/***********************************************************/ -/* AMCC_TODO: - * Find out of the choice for the emac for MDIO is from the bridges, - * i.e. ZMII or RGMII as approporiate. If the bridges are not used - * to determine the emac for MDIO, then is the SDR0_ETH_CFG[MDIO_SEL] - * used? If so, then this routine below does not apply to the 460EX/GT. - * - * sr: Currently on 460EX only EMAC0 works with MDIO, so we always - * return EMAC0 offset here - * vg: For 460EX/460GT if internal GPCS PHY address is specified - * return appropriate EMAC offset - */ -unsigned int miiphy_getemac_offset(u8 addr) -{ -#if (defined(CONFIG_440) && \ - !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ - !defined(CONFIG_460EX) && !defined(CONFIG_460GT)) && \ - defined(CONFIG_NET_MULTI) - unsigned long zmii; - unsigned long eoffset; - - /* Need to find out which mdi port we're using */ - zmii = in_be32((void *)ZMII0_FER); - - if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0))) - /* using port 0 */ - eoffset = 0; - - else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1))) - /* using port 1 */ - eoffset = 0x100; - - else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2))) - /* using port 2 */ - eoffset = 0x400; - - else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3))) - /* using port 3 */ - eoffset = 0x600; - - else { - /* None of the mdi ports are enabled! */ - /* enable port 0 */ - zmii |= ZMII_FER_MDI << ZMII_FER_V (0); - out_be32((void *)ZMII0_FER, zmii); - eoffset = 0; - /* need to soft reset port 0 */ - zmii = in_be32((void *)EMAC0_MR0); - zmii |= EMAC_MR0_SRST; - out_be32((void *)EMAC0_MR0, zmii); - } - - return (eoffset); -#else - -#if defined(CONFIG_NET_MULTI) && defined(CONFIG_405EX) - unsigned long rgmii; - int devnum = 1; - - rgmii = in_be32((void *)RGMII_FER); - if (rgmii & (1 << (19 - devnum))) - return 0x100; -#endif - -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) - u32 eoffset = 0; - - switch (addr) { -#if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR) - case CONFIG_GPCS_PHY1_ADDR: - if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x100))) - eoffset = 0x100; - break; -#endif -#if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR) - case CONFIG_GPCS_PHY2_ADDR: - if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x300))) - eoffset = 0x300; - break; -#endif -#if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR) - case CONFIG_GPCS_PHY3_ADDR: - if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x400))) - eoffset = 0x400; - break; -#endif - default: - eoffset = 0; - break; - } - return eoffset; -#endif - - return 0; -#endif -} - -static int emac_miiphy_wait(u32 emac_reg) -{ - u32 sta_reg; - int i; - - /* wait for completion */ - i = 0; - do { - sta_reg = in_be32((void *)EMAC0_STACR + emac_reg); - if (i++ > 5) { - debug("%s [%d]: Timeout! EMAC0_STACR=0x%0x\n", __func__, - __LINE__, sta_reg); - return -1; - } - udelay(10); - } while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK); - - return 0; -} - -static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value) -{ - u32 emac_reg; - u32 sta_reg; - - emac_reg = miiphy_getemac_offset(addr); - - /* wait for completion */ - if (emac_miiphy_wait(emac_reg) != 0) - return -1; - - sta_reg = reg; /* reg address */ - - /* set clock (50MHz) and read flags */ -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ - defined(CONFIG_405EX) -#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ - sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | cmd; -#else - sta_reg |= cmd; -#endif -#else - sta_reg = (sta_reg | cmd) & ~EMAC_STACR_CLK_100MHZ; -#endif - - /* Some boards (mainly 405EP based) define the PHY clock freqency fixed */ - sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; - sta_reg = sta_reg | ((u32)addr << 5); /* Phy address */ - sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */ - if (cmd == EMAC_STACR_WRITE) - memcpy(&sta_reg, &value, 2); /* put in data */ - - out_be32((void *)EMAC0_STACR + emac_reg, sta_reg); - debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg); - - /* wait for completion */ - if (emac_miiphy_wait(emac_reg) != 0) - return -1; - - debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg); - if ((sta_reg & EMAC_STACR_PHYE) != 0) - return -1; - - return 0; -} - -int emac4xx_miiphy_read (const char *devname, unsigned char addr, unsigned char reg, - unsigned short *value) -{ - unsigned long sta_reg; - unsigned long emac_reg; - - emac_reg = miiphy_getemac_offset(addr); - - if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0) - return -1; - - sta_reg = in_be32((void *)EMAC0_STACR + emac_reg); - *value = sta_reg >> 16; - - return 0; -} - -/***********************************************************/ -/* write a phy reg and return the value with a rc */ -/***********************************************************/ - -int emac4xx_miiphy_write (const char *devname, unsigned char addr, unsigned char reg, - unsigned short value) -{ - return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value); -} diff --git a/arch/powerpc/cpu/ppc4xx/reginfo.c b/arch/powerpc/cpu/ppc4xx/reginfo.c deleted file mode 100644 index 2f1ab9e..0000000 --- a/arch/powerpc/cpu/ppc4xx/reginfo.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - *(C) Copyright 2005-2009 Netstal Maschinen AG - * Bruno Hars (Bruno.Hars@netstal.com) - * Niklaus Giger (Niklaus.Giger@netstal.com) - * - * This source code is free software; you can redistribute it - * and/or modify it in source code form 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 - */ - -/* - * reginfo.c - register dump of HW-configuratin register for PPC4xx based board - */ - -#include <common.h> -#include <command.h> -#include <asm/processor.h> -#include <asm/io.h> -#include <asm/ppc4xx-uic.h> -#include <asm/ppc4xx-emac.h> - -enum REGISTER_TYPE { - IDCR1, /* Indirectly Accessed DCR via SDRAM0_CFGADDR/SDRAM0_CFGDATA */ - IDCR2, /* Indirectly Accessed DCR via EBC0_CFGADDR/EBC0_CFGDATA */ - IDCR3, /* Indirectly Accessed DCR via EBM0_CFGADDR/EBM0_CFGDATA */ - IDCR4, /* Indirectly Accessed DCR via PPM0_CFGADDR/PPM0_CFGDATA */ - IDCR5, /* Indirectly Accessed DCR via CPR0_CFGADDR/CPR0_CFGDATA */ - IDCR6, /* Indirectly Accessed DCR via SDR0_CFGADDR/SDR0_CFGDATA */ - MM /* Directly Accessed MMIO Register */ -}; - -struct cpu_register { - char *name; - enum REGISTER_TYPE type; - u32 address; -}; - -/* - * PPC440EPx registers ordered for output - * name type addr size - * ------------------------------------------- - */ - -const struct cpu_register ppc4xx_reg[] = { - {"PB0CR", IDCR2, PB0CR}, - {"PB0AP", IDCR2, PB0AP}, - {"PB1CR", IDCR2, PB1CR}, - {"PB1AP", IDCR2, PB1AP}, - {"PB2CR", IDCR2, PB2CR}, - {"PB2AP", IDCR2, PB2AP}, - {"PB3CR", IDCR2, PB3CR}, - {"PB3AP", IDCR2, PB3AP}, - - {"PB4CR", IDCR2, PB4CR}, - {"PB4AP", IDCR2, PB4AP}, -#if !defined(CONFIG_405EP) - {"PB5CR", IDCR2, PB5CR}, - {"PB5AP", IDCR2, PB5AP}, - {"PB6CR", IDCR2, PB6CR}, - {"PB6AP", IDCR2, PB6AP}, - {"PB7CR", IDCR2, PB7CR}, - {"PB7AP", IDCR2, PB7AP}, -#endif - - {"PBEAR", IDCR2, PBEAR}, -#if defined(CONFIG_405EP) || defined (CONFIG_405GP) - {"PBESR0", IDCR2, PBESR0}, - {"PBESR1", IDCR2, PBESR1}, -#endif - {"EBC0_CFG", IDCR2, EBC0_CFG}, - -#ifdef CONFIG_405GP - {"SDRAM0_BESR0", IDCR1, SDRAM0_BESR0}, - {"SDRAM0_BESRS0", IDCR1, SDRAM0_BESRS0}, - {"SDRAM0_BESR1", IDCR1, SDRAM0_BESR1}, - {"SDRAM0_BESRS1", IDCR1, SDRAM0_BESRS1}, - {"SDRAM0_BEAR", IDCR1, SDRAM0_BEAR}, - {"SDRAM0_CFG", IDCR1, SDRAM0_CFG}, - {"SDRAM0_RTR", IDCR1, SDRAM0_RTR}, - {"SDRAM0_PMIT", IDCR1, SDRAM0_PMIT}, - - {"SDRAM0_B0CR", IDCR1, SDRAM0_B0CR}, - {"SDRAM0_B1CR", IDCR1, SDRAM0_B1CR}, - {"SDRAM0_B2CR", IDCR1, SDRAM0_B2CR}, - {"SDRAM0_B3CR", IDCR1, SDRAM0_B1CR}, - {"SDRAM0_TR", IDCR1, SDRAM0_TR}, - {"SDRAM0_ECCCFG", IDCR1, SDRAM0_B1CR}, - {"SDRAM0_ECCESR", IDCR1, SDRAM0_ECCESR}, - - -#endif - -#ifdef CONFIG_440EPX - {"SDR0_SDSTP0", IDCR6, SDR0_SDSTP0}, - {"SDR0_SDSTP1", IDCR6, SDR0_SDSTP1}, - {"SDR0_SDSTP2", IDCR6, SDR0_SDSTP2}, - {"SDR0_SDSTP3", IDCR6, SDR0_SDSTP3}, - {"SDR0_CUST0", IDCR6, SDR0_CUST0}, - {"SDR0_CUST1", IDCR6, SDR0_CUST1}, - {"SDR0_EBC", IDCR6, SDR0_EBC}, - {"SDR0_AMP0", IDCR6, SDR0_AMP0}, - {"SDR0_AMP1", IDCR6, SDR0_AMP1}, - {"SDR0_CP440", IDCR6, SDR0_CP440}, - {"SDR0_CRYP0", IDCR6, SDR0_CRYP0}, - {"SDR0_DDRCFG", IDCR6, SDR0_DDRCFG}, - {"SDR0_EMAC0RXST", IDCR6, SDR0_EMAC0RXST}, - {"SDR0_EMAC0TXST", IDCR6, SDR0_EMAC0TXST}, - {"SDR0_MFR", IDCR6, SDR0_MFR}, - {"SDR0_PCI0", IDCR6, SDR0_PCI0}, - {"SDR0_PFC0", IDCR6, SDR0_PFC0}, - {"SDR0_PFC1", IDCR6, SDR0_PFC1}, - {"SDR0_PFC2", IDCR6, SDR0_PFC2}, - {"SDR0_PFC4", IDCR6, SDR0_PFC4}, - {"SDR0_UART0", IDCR6, SDR0_UART0}, - {"SDR0_UART1", IDCR6, SDR0_UART1}, - {"SDR0_UART2", IDCR6, SDR0_UART2}, - {"SDR0_UART3", IDCR6, SDR0_UART3}, - {"DDR0_02", IDCR1, DDR0_02}, - {"DDR0_00", IDCR1, DDR0_00}, - {"DDR0_01", IDCR1, DDR0_01}, - {"DDR0_03", IDCR1, DDR0_03}, - {"DDR0_04", IDCR1, DDR0_04}, - {"DDR0_05", IDCR1, DDR0_05}, - {"DDR0_06", IDCR1, DDR0_06}, - {"DDR0_07", IDCR1, DDR0_07}, - {"DDR0_08", IDCR1, DDR0_08}, - {"DDR0_09", IDCR1, DDR0_09}, - {"DDR0_10", IDCR1, DDR0_10}, - {"DDR0_11", IDCR1, DDR0_11}, - {"DDR0_12", IDCR1, DDR0_12}, - {"DDR0_14", IDCR1, DDR0_14}, - {"DDR0_17", IDCR1, DDR0_17}, - {"DDR0_18", IDCR1, DDR0_18}, - {"DDR0_19", IDCR1, DDR0_19}, - {"DDR0_20", IDCR1, DDR0_20}, - {"DDR0_21", IDCR1, DDR0_21}, - {"DDR0_22", IDCR1, DDR0_22}, - {"DDR0_23", IDCR1, DDR0_23}, - {"DDR0_24", IDCR1, DDR0_24}, - {"DDR0_25", IDCR1, DDR0_25}, - {"DDR0_26", IDCR1, DDR0_26}, - {"DDR0_27", IDCR1, DDR0_27}, - {"DDR0_28", IDCR1, DDR0_28}, - {"DDR0_31", IDCR1, DDR0_31}, - {"DDR0_32", IDCR1, DDR0_32}, - {"DDR0_33", IDCR1, DDR0_33}, - {"DDR0_34", IDCR1, DDR0_34}, - {"DDR0_35", IDCR1, DDR0_35}, - {"DDR0_36", IDCR1, DDR0_36}, - {"DDR0_37", IDCR1, DDR0_37}, - {"DDR0_38", IDCR1, DDR0_38}, - {"DDR0_39", IDCR1, DDR0_39}, - {"DDR0_40", IDCR1, DDR0_40}, - {"DDR0_41", IDCR1, DDR0_41}, - {"DDR0_42", IDCR1, DDR0_42}, - {"DDR0_43", IDCR1, DDR0_43}, - {"DDR0_44", IDCR1, DDR0_44}, - {"CPR0_ICFG", IDCR5, CPR0_ICFG}, - {"CPR0_MALD", IDCR5, CPR0_MALD}, - {"CPR0_OPBD00", IDCR5, CPR0_OPBD0}, - {"CPR0_PERD0", IDCR5, CPR0_PERD}, - {"CPR0_PLLC0", IDCR5, CPR0_PLLC}, - {"CPR0_PLLD0", IDCR5, CPR0_PLLD}, - {"CPR0_PRIMAD0", IDCR5, CPR0_PRIMAD0}, - {"CPR0_PRIMBD0", IDCR5, CPR0_PRIMBD0}, - {"CPR0_SPCID", IDCR5, CPR0_SPCID}, - {"SPI0_MODE", MM, SPI0_MODE}, - {"IIC0_CLKDIV", MM, PCIL0_PMM1MA}, - {"PCIL0_PMM0MA", MM, PCIL0_PMM0MA}, - {"PCIL0_PMM1MA", MM, PCIL0_PMM1MA}, - {"PCIL0_PTM1LA", MM, PCIL0_PMM1MA}, - {"PCIL0_PTM1MS", MM, PCIL0_PTM1MS}, - {"PCIL0_PTM2LA", MM, PCIL0_PMM1MA}, - {"PCIL0_PTM2MS", MM, PCIL0_PTM2MS}, - {"ZMII0_FER", MM, ZMII0_FER}, - {"ZMII0_SSR", MM, ZMII0_SSR}, - {"EMAC0_IPGVR", MM, EMAC0_IPGVR}, - {"EMAC0_MR1", MM, EMAC0_MR1}, - {"EMAC0_PTR", MM, EMAC0_PTR}, - {"EMAC0_RWMR", MM, EMAC0_RWMR}, - {"EMAC0_STACR", MM, EMAC0_STACR}, - {"EMAC0_TMR0", MM, EMAC0_TMR0}, - {"EMAC0_TMR1", MM, EMAC0_TMR1}, - {"EMAC0_TRTR", MM, EMAC0_TRTR}, - {"EMAC1_MR1", MM, EMAC1_MR1}, - {"GPIO0_OR", MM, GPIO0_OR}, - {"GPIO1_OR", MM, GPIO1_OR}, - {"GPIO0_TCR", MM, GPIO0_TCR}, - {"GPIO1_TCR", MM, GPIO1_TCR}, - {"GPIO0_ODR", MM, GPIO0_ODR}, - {"GPIO1_ODR", MM, GPIO1_ODR}, - {"GPIO0_OSRL", MM, GPIO0_OSRL}, - {"GPIO0_OSRH", MM, GPIO0_OSRH}, - {"GPIO1_OSRL", MM, GPIO1_OSRL}, - {"GPIO1_OSRH", MM, GPIO1_OSRH}, - {"GPIO0_TSRL", MM, GPIO0_TSRL}, - {"GPIO0_TSRH", MM, GPIO0_TSRH}, - {"GPIO1_TSRL", MM, GPIO1_TSRL}, - {"GPIO1_TSRH", MM, GPIO1_TSRH}, - {"GPIO0_IR", MM, GPIO0_IR}, - {"GPIO1_IR", MM, GPIO1_IR}, - {"GPIO0_ISR1L", MM, GPIO0_ISR1L}, - {"GPIO0_ISR1H", MM, GPIO0_ISR1H}, - {"GPIO1_ISR1L", MM, GPIO1_ISR1L}, - {"GPIO1_ISR1H", MM, GPIO1_ISR1H}, - {"GPIO0_ISR2L", MM, GPIO0_ISR2L}, - {"GPIO0_ISR2H", MM, GPIO0_ISR2H}, - {"GPIO1_ISR2L", MM, GPIO1_ISR2L}, - {"GPIO1_ISR2H", MM, GPIO1_ISR2H}, - {"GPIO0_ISR3L", MM, GPIO0_ISR3L}, - {"GPIO0_ISR3H", MM, GPIO0_ISR3H}, - {"GPIO1_ISR3L", MM, GPIO1_ISR3L}, - {"GPIO1_ISR3H", MM, GPIO1_ISR3H}, - {"SDR0_USB2PHY0CR", IDCR6, SDR0_USB2PHY0CR}, - {"SDR0_USB2H0CR", IDCR6, SDR0_USB2H0CR}, - {"SDR0_USB2D0CR", IDCR6, SDR0_USB2D0CR}, -#endif -}; - -/* - * CPU Register dump of PPC4xx HW configuration registers - * Output: first all DCR-registers, then in order of struct ppc4xx_reg - */ -#define PRINT_DCR(dcr) printf("0x%08x %-16s: 0x%08x\n", dcr,#dcr, mfdcr(dcr)); - -void ppc4xx_reginfo(void) -{ - unsigned int i; - unsigned int n; - u32 value; - enum REGISTER_TYPE type; -#if defined (CONFIG_405EP) - printf("Dump PPC405EP HW configuration registers\n\n"); -#elif CONFIG_405GP - printf ("Dump 405GP HW configuration registers\n\n"); -#elif CONFIG_440EPX - printf("Dump PPC440EPx HW configuration registers\n\n"); -#endif - printf("MSR: 0x%08x\n", mfmsr()); - - printf ("\nUniversal Interrupt Controller Regs\n"); - PRINT_DCR(UIC0SR); - PRINT_DCR(UIC0ER); - PRINT_DCR(UIC0CR); - PRINT_DCR(UIC0PR); - PRINT_DCR(UIC0TR); - PRINT_DCR(UIC0MSR); - PRINT_DCR(UIC0VR); - PRINT_DCR(UIC0VCR); - -#if (UIC_MAX > 1) - PRINT_DCR(UIC2SR); - PRINT_DCR(UIC2ER); - PRINT_DCR(UIC2CR); - PRINT_DCR(UIC2PR); - PRINT_DCR(UIC2TR); - PRINT_DCR(UIC2MSR); - PRINT_DCR(UIC2VR); - PRINT_DCR(UIC2VCR); -#endif - -#if (UIC_MAX > 2) - PRINT_DCR(UIC2SR); - PRINT_DCR(UIC2ER); - PRINT_DCR(UIC2CR); - PRINT_DCR(UIC2PR); - PRINT_DCR(UIC2TR); - PRINT_DCR(UIC2MSR); - PRINT_DCR(UIC2VR); - PRINT_DCR(UIC2VCR); -#endif - -#if (UIC_MAX > 3) - PRINT_DCR(UIC3SR); - PRINT_DCR(UIC3ER); - PRINT_DCR(UIC3CR); - PRINT_DCR(UIC3PR); - PRINT_DCR(UIC3TR); - PRINT_DCR(UIC3MSR); - PRINT_DCR(UIC3VR); - PRINT_DCR(UIC3VCR); -#endif - -#if defined (CONFIG_405EP) || defined (CONFIG_405GP) - printf ("\n\nDMA Channels\n"); - PRINT_DCR(DMASR); - PRINT_DCR(DMASGC); - PRINT_DCR(DMAADR); - - PRINT_DCR(DMACR0); - PRINT_DCR(DMACT0); - PRINT_DCR(DMADA0); - PRINT_DCR(DMASA0); - PRINT_DCR(DMASB0); - - PRINT_DCR(DMACR1); - PRINT_DCR(DMACT1); - PRINT_DCR(DMADA1); - PRINT_DCR(DMASA1); - PRINT_DCR(DMASB1); - - PRINT_DCR(DMACR2); - PRINT_DCR(DMACT2); - PRINT_DCR(DMADA2); - PRINT_DCR(DMASA2); - PRINT_DCR(DMASB2); - - PRINT_DCR(DMACR3); - PRINT_DCR(DMACT3); - PRINT_DCR(DMADA3); - PRINT_DCR(DMASA3); - PRINT_DCR(DMASB3); -#endif - - printf ("\n\nVarious HW-Configuration registers\n"); -#if defined (CONFIG_440EPX) - PRINT_DCR(MAL0_CFG); - PRINT_DCR(CPM0_ER); - PRINT_DCR(CPM1_ER); - PRINT_DCR(PLB4A0_ACR); - PRINT_DCR(PLB4A1_ACR); - PRINT_DCR(PLB3A0_ACR); - PRINT_DCR(OPB2PLB40_BCTRL); - PRINT_DCR(P4P3BO0_CFG); -#endif - n = sizeof(ppc4xx_reg) / sizeof(ppc4xx_reg[0]); - for (i = 0; i < n; i++) { - value = 0; - type = ppc4xx_reg[i].type; - switch (type) { - case IDCR1: /* Indirect via SDRAM0_CFGADDR/DDR0_CFGDATA */ - mtdcr(SDRAM0_CFGADDR, ppc4xx_reg[i].address); - value = mfdcr(SDRAM0_CFGDATA); - break; - case IDCR2: /* Indirect via EBC0_CFGADDR/EBC0_CFGDATA */ - mtdcr(EBC0_CFGADDR, ppc4xx_reg[i].address); - value = mfdcr(EBC0_CFGDATA); - break; - case IDCR5: /* Indirect via CPR0_CFGADDR/CPR0_CFGDATA */ - mtdcr(CPR0_CFGADDR, ppc4xx_reg[i].address); - value = mfdcr(CPR0_CFGDATA); - break; - case IDCR6: /* Indirect via SDR0_CFGADDR/SDR0_CFGDATA */ - mtdcr(SDR0_CFGADDR, ppc4xx_reg[i].address); - value = mfdcr(SDR0_CFGDATA); - break; - case MM: /* Directly Accessed MMIO Register */ - value = in_be32((const volatile unsigned __iomem *) - ppc4xx_reg[i].address); - break; - default: - printf("\nERROR: struct entry %d: unknown register" - "type\n", i); - break; - } - printf("0x%08x %-16s: 0x%08x\n",ppc4xx_reg[i].address, - ppc4xx_reg[i].name, value); - } -} diff --git a/arch/powerpc/cpu/ppc4xx/resetvec.S b/arch/powerpc/cpu/ppc4xx/resetvec.S deleted file mode 100644 index b3308bd..0000000 --- a/arch/powerpc/cpu/ppc4xx/resetvec.S +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright MontaVista Software Incorporated, 2000 */ -#include <config.h> - .section .resetvec,"ax" -#if defined(CONFIG_440) - b _start_440 -#else -#if defined(CONFIG_BOOT_PCI) && defined(CONFIG_MIP405) - b _start_pci -#else - b _start -#endif -#endif diff --git a/arch/powerpc/cpu/ppc4xx/sdram.c b/arch/powerpc/cpu/ppc4xx/sdram.c deleted file mode 100644 index b827daf..0000000 --- a/arch/powerpc/cpu/ppc4xx/sdram.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * (C) Copyright 2005-2007 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * (C) Copyright 2006 - * DAVE Srl <www.dave-tech.it> - * - * (C) Copyright 2002-2004 - * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/ppc4xx.h> -#include <asm/processor.h> -#include "sdram.h" -#include "ecc.h" - -#ifdef CONFIG_SDRAM_BANK0 - -#ifndef CONFIG_440 - -#ifndef CONFIG_SYS_SDRAM_TABLE -sdram_conf_t mb0cf[] = { - {(128 << 20), 13, 0x000A4001}, /* (0-128MB) Address Mode 3, 13x10(4) */ - {(64 << 20), 13, 0x00084001}, /* (0-64MB) Address Mode 3, 13x9(4) */ - {(32 << 20), 12, 0x00062001}, /* (0-32MB) Address Mode 2, 12x9(4) */ - {(16 << 20), 12, 0x00046001}, /* (0-16MB) Address Mode 4, 12x8(4) */ - {(4 << 20), 11, 0x00008001}, /* (0-4MB) Address Mode 5, 11x8(2) */ -}; -#else -sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE; -#endif - -#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0])) - -#ifdef CONFIG_SYS_SDRAM_CASL -static ulong ns2clks(ulong ns) -{ - ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10); - - return ((ns * 10) + bus_period_x_10) / bus_period_x_10; -} -#endif /* CONFIG_SYS_SDRAM_CASL */ - -static ulong compute_sdtr1(ulong speed) -{ -#ifdef CONFIG_SYS_SDRAM_CASL - ulong tmp; - ulong sdtr1 = 0; - - /* CASL */ - if (CONFIG_SYS_SDRAM_CASL < 2) - sdtr1 |= (1 << SDRAM0_TR_CASL); - else - if (CONFIG_SYS_SDRAM_CASL > 4) - sdtr1 |= (3 << SDRAM0_TR_CASL); - else - sdtr1 |= ((CONFIG_SYS_SDRAM_CASL-1) << SDRAM0_TR_CASL); - - /* PTA */ - tmp = ns2clks(CONFIG_SYS_SDRAM_PTA); - if ((tmp >= 2) && (tmp <= 4)) - sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA); - else - sdtr1 |= ((4-1) << SDRAM0_TR_PTA); - - /* CTP */ - tmp = ns2clks(CONFIG_SYS_SDRAM_CTP); - if ((tmp >= 2) && (tmp <= 4)) - sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP); - else - sdtr1 |= ((4-1) << SDRAM0_TR_CTP); - - /* LDF */ - tmp = ns2clks(CONFIG_SYS_SDRAM_LDF); - if ((tmp >= 2) && (tmp <= 4)) - sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF); - else - sdtr1 |= ((2-1) << SDRAM0_TR_LDF); - - /* RFTA */ - tmp = ns2clks(CONFIG_SYS_SDRAM_RFTA); - if ((tmp >= 4) && (tmp <= 10)) - sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA); - else - sdtr1 |= ((10-4) << SDRAM0_TR_RFTA); - - /* RCD */ - tmp = ns2clks(CONFIG_SYS_SDRAM_RCD); - if ((tmp >= 2) && (tmp <= 4)) - sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD); - else - sdtr1 |= ((4-1) << SDRAM0_TR_RCD); - - return sdtr1; -#else /* CONFIG_SYS_SDRAM_CASL */ - /* - * If no values are configured in the board config file - * use the default values, which seem to be ok for most - * boards. - * - * REMARK: - * For new board ports we strongly recommend to define the - * correct values for the used SDRAM chips in your board - * config file (see PPChameleonEVB.h) - */ - if (speed > 100000000) { - /* - * 133 MHz SDRAM - */ - return 0x01074015; - } else { - /* - * default: 100 MHz SDRAM - */ - return 0x0086400d; - } -#endif /* CONFIG_SYS_SDRAM_CASL */ -} - -/* refresh is expressed in ms */ -static ulong compute_rtr(ulong speed, ulong rows, ulong refresh) -{ -#ifdef CONFIG_SYS_SDRAM_CASL - ulong tmp; - - tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000); - tmp /= 1000000; - - return ((tmp & 0x00003FF8) << 16); -#else /* CONFIG_SYS_SDRAM_CASL */ - if (speed > 100000000) { - /* - * 133 MHz SDRAM - */ - return 0x07f00000; - } else { - /* - * default: 100 MHz SDRAM - */ - return 0x05f00000; - } -#endif /* CONFIG_SYS_SDRAM_CASL */ -} - -/* - * Autodetect onboard SDRAM on 405 platforms - */ -phys_size_t initdram(int board_type) -{ - ulong speed; - ulong sdtr1; - int i; - - /* - * Determine SDRAM speed - */ - speed = get_bus_freq(0); /* parameter not used on ppc4xx */ - - /* - * sdtr1 (register SDRAM0_TR) must take into account timings listed - * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into - * account actual SDRAM size. So we can set up sdtr1 according to what - * is specified in board configuration file while rtr dependds on SDRAM - * size we are assuming before detection. - */ - sdtr1 = compute_sdtr1(speed); - - for (i=0; i<N_MB0CF; i++) { - /* - * Disable memory controller. - */ - mtsdram(SDRAM0_CFG, 0x00000000); - - /* - * Set MB0CF for bank 0. - */ - mtsdram(SDRAM0_B0CR, mb0cf[i].reg); - mtsdram(SDRAM0_TR, sdtr1); - mtsdram(SDRAM0_RTR, compute_rtr(speed, mb0cf[i].rows, 64)); - - udelay(200); - - /* - * Set memory controller options reg, MCOPT1. - * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst - * read/prefetch. - */ - mtsdram(SDRAM0_CFG, 0x80800000); - - udelay(10000); - - if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) { - phys_size_t size = mb0cf[i].size; - - /* - * OK, size detected. Enable second bank if - * defined (assumes same type as bank 0) - */ -#ifdef CONFIG_SDRAM_BANK1 - mtsdram(SDRAM0_CFG, 0x00000000); - mtsdram(SDRAM0_B1CR, mb0cf[i].size | mb0cf[i].reg); - mtsdram(SDRAM0_CFG, 0x80800000); - udelay(10000); - - /* - * Check if 2nd bank is really available. - * If the size not equal to the size of the first - * bank, then disable the 2nd bank completely. - */ - if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size) != - mb0cf[i].size) { - mtsdram(SDRAM0_B1CR, 0); - mtsdram(SDRAM0_CFG, 0); - } else { - /* - * We have two identical banks, so the size - * is twice the bank size - */ - size = 2 * size; - } -#endif - - /* - * OK, size detected -> all done - */ - return size; - } - } - - return 0; -} - -#else /* CONFIG_440 */ - -/* - * Define some default values. Those can be overwritten in the - * board config file. - */ - -#ifndef CONFIG_SYS_SDRAM_TABLE -sdram_conf_t mb0cf[] = { - {(256 << 20), 13, 0x000C4001}, /* 256MB mode 3, 13x10(4) */ - {(128 << 20), 13, 0x000A4001}, /* 128MB mode 3, 13x10(4) */ - {(64 << 20), 12, 0x00082001} /* 64MB mode 2, 12x9(4) */ -}; -#else -sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE; -#endif - -#ifndef CONFIG_SYS_SDRAM0_TR0 -#define CONFIG_SYS_SDRAM0_TR0 0x41094012 -#endif - -#ifndef CONFIG_SYS_SDRAM0_WDDCTR -#define CONFIG_SYS_SDRAM0_WDDCTR 0x00000000 /* wrcp=0 dcd=0 */ -#endif - -#ifndef CONFIG_SYS_SDRAM0_RTR -#define CONFIG_SYS_SDRAM0_RTR 0x04100000 /* 7.8us @ 133MHz PLB */ -#endif - -#ifndef CONFIG_SYS_SDRAM0_CFG0 -#define CONFIG_SYS_SDRAM0_CFG0 0x82000000 /* DCEN=1, PMUD=0, 64-bit */ -#endif - -#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0])) - -#define NUM_TRIES 64 -#define NUM_READS 10 - -static void sdram_tr1_set(int ram_address, int* tr1_value) -{ - int i; - int j, k; - volatile unsigned int* ram_pointer = (unsigned int *)ram_address; - int first_good = -1, last_bad = 0x1ff; - - unsigned long test[NUM_TRIES] = { - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, - 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 }; - - /* go through all possible SDRAM0_TR1[RDCT] values */ - for (i=0; i<=0x1ff; i++) { - /* set the current value for TR1 */ - mtsdram(SDRAM0_TR1, (0x80800800 | i)); - - /* write values */ - for (j=0; j<NUM_TRIES; j++) { - ram_pointer[j] = test[j]; - - /* clear any cache at ram location */ - __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); - } - - /* read values back */ - for (j=0; j<NUM_TRIES; j++) { - for (k=0; k<NUM_READS; k++) { - /* clear any cache at ram location */ - __asm__("dcbf 0,%0": :"r" (&ram_pointer[j])); - - if (ram_pointer[j] != test[j]) - break; - } - - /* read error */ - if (k != NUM_READS) - break; - } - - /* we have a SDRAM0_TR1[RDCT] that is part of the window */ - if (j == NUM_TRIES) { - if (first_good == -1) - first_good = i; /* found beginning of window */ - } else { /* bad read */ - /* if we have not had a good read then don't care */ - if (first_good != -1) { - /* first failure after a good read */ - last_bad = i-1; - break; - } - } - } - - /* return the current value for TR1 */ - *tr1_value = (first_good + last_bad) / 2; -} - -/* - * Autodetect onboard DDR SDRAM on 440 platforms - * - * NOTE: Some of the hardcoded values are hardware dependant, - * so this should be extended for other future boards - * using this routine! - */ -phys_size_t initdram(int board_type) -{ - int i; - int tr1_bank1; - -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ - defined(CONFIG_440GR) || defined(CONFIG_440SP) - /* - * Soft-reset SDRAM controller. - */ - mtsdr(SDR0_SRST, SDR0_SRST_DMC); - mtsdr(SDR0_SRST, 0x00000000); -#endif - - for (i=0; i<N_MB0CF; i++) { - /* - * Disable memory controller. - */ - mtsdram(SDRAM0_CFG0, 0x00000000); - - /* - * Setup some default - */ - mtsdram(SDRAM0_UABBA, 0x00000000); /* ubba=0 (default) */ - mtsdram(SDRAM0_SLIO, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ - mtsdram(SDRAM0_DEVOPT, 0x00000000); /* dll=0 ds=0 (normal) */ - mtsdram(SDRAM0_WDDCTR, CONFIG_SYS_SDRAM0_WDDCTR); - mtsdram(SDRAM0_CLKTR, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */ - - /* - * Following for CAS Latency = 2.5 @ 133 MHz PLB - */ - mtsdram(SDRAM0_B0CR, mb0cf[i].reg); - mtsdram(SDRAM0_TR0, CONFIG_SYS_SDRAM0_TR0); - mtsdram(SDRAM0_TR1, 0x80800800); /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/ - mtsdram(SDRAM0_RTR, CONFIG_SYS_SDRAM0_RTR); - mtsdram(SDRAM0_CFG1, 0x00000000); /* Self-refresh exit, disable PM*/ - udelay(400); /* Delay 200 usecs (min) */ - - /* - * Enable the controller, then wait for DCEN to complete - */ - mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0); - udelay(10000); - - if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) { - phys_size_t size = mb0cf[i].size; - /* - * Optimize TR1 to current hardware environment - */ - sdram_tr1_set(0x00000000, &tr1_bank1); - mtsdram(SDRAM0_TR1, (tr1_bank1 | 0x80800800)); - - - /* - * OK, size detected. Enable second bank if - * defined (assumes same type as bank 0) - */ -#ifdef CONFIG_SDRAM_BANK1 - mtsdram(SDRAM0_CFG0, 0); - mtsdram(SDRAM0_B1CR, mb0cf[i].size | mb0cf[i].reg); - mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0); - udelay(10000); - - /* - * Check if 2nd bank is really available. - * If the size not equal to the size of the first - * bank, then disable the 2nd bank completely. - */ - if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size) - != mb0cf[i].size) { - mtsdram(SDRAM0_CFG0, 0); - mtsdram(SDRAM0_B1CR, 0); - mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0); - udelay(10000); - } else { - /* - * We have two identical banks, so the size - * is twice the bank size - */ - size = 2 * size; - } -#endif - -#ifdef CONFIG_SDRAM_ECC - ecc_init(0, size); -#endif - - /* - * OK, size detected -> all done - */ - return size; - } - } - - return 0; /* nothing found ! */ -} - -#endif /* CONFIG_440 */ - -#endif /* CONFIG_SDRAM_BANK0 */ diff --git a/arch/powerpc/cpu/ppc4xx/sdram.h b/arch/powerpc/cpu/ppc4xx/sdram.h deleted file mode 100644 index bea3376..0000000 --- a/arch/powerpc/cpu/ppc4xx/sdram.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * (C) Copyright 2006 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * (C) Copyright 2006 - * DAVE Srl <www.dave-tech.it> - * - * 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 _SDRAM_H_ -#define _SDRAM_H_ - -#include <config.h> - -#define ONE_BILLION 1000000000 - -struct sdram_conf_s { - unsigned long size; - int rows; - unsigned long reg; -}; - -typedef struct sdram_conf_s sdram_conf_t; - -/* Bitfields offsets */ -#define SDRAM0_TR_CASL (31 - 8) -#define SDRAM0_TR_PTA (31 - 13) -#define SDRAM0_TR_CTP (31 - 15) -#define SDRAM0_TR_LDF (31 - 17) -#define SDRAM0_TR_RFTA (31 - 29) -#define SDRAM0_TR_RCD (31 - 31) - -#ifdef CONFIG_SYS_SDRAM_CL -/* SDRAM timings [ns] according to AMCC/IBM names (see SDRAM_faq.doc) */ -#define CONFIG_SYS_SDRAM_CASL CONFIG_SYS_SDRAM_CL -#define CONFIG_SYS_SDRAM_PTA CONFIG_SYS_SDRAM_tRP -#define CONFIG_SYS_SDRAM_CTP (CONFIG_SYS_SDRAM_tRC - CONFIG_SYS_SDRAM_tRCD - CONFIG_SYS_SDRAM_tRP) -#define CONFIG_SYS_SDRAM_LDF 0 -#ifdef CONFIG_SYS_SDRAM_tRFC -#define CONFIG_SYS_SDRAM_RFTA CONFIG_SYS_SDRAM_tRFC -#else -#define CONFIG_SYS_SDRAM_RFTA CONFIG_SYS_SDRAM_tRC -#endif -#define CONFIG_SYS_SDRAM_RCD CONFIG_SYS_SDRAM_tRCD -#endif /* #ifdef CONFIG_SYS_SDRAM_CL */ - -/* - * Some defines for the 440 DDR controller - */ -#define SDRAM_CFG0_DC_EN 0x80000000 /* SDRAM Controller Enable */ -#define SDRAM_CFG0_MEMCHK 0x30000000 /* Memory data error checking mask*/ -#define SDRAM_CFG0_MEMCHK_NON 0x00000000 /* No ECC generation */ -#define SDRAM_CFG0_MEMCHK_GEN 0x20000000 /* ECC generation */ -#define SDRAM_CFG0_MEMCHK_CHK 0x30000000 /* ECC generation and checking */ -#define SDRAM_CFG0_DRAMWDTH 0x02000000 /* DRAM width mask */ -#define SDRAM_CFG0_DRAMWDTH_32 0x00000000 /* 32 bits */ -#define SDRAM_CFG0_DRAMWDTH_64 0x02000000 /* 64 bits */ - -#endif diff --git a/arch/powerpc/cpu/ppc4xx/speed.c b/arch/powerpc/cpu/ppc4xx/speed.c deleted file mode 100644 index 09d6671..0000000 --- a/arch/powerpc/cpu/ppc4xx/speed.c +++ /dev/null @@ -1,1250 +0,0 @@ -/* - * (C) Copyright 2000-2008 - * 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 <common.h> -#include <ppc_asm.tmpl> -#include <asm/ppc4xx.h> -#include <asm/processor.h> - -DECLARE_GLOBAL_DATA_PTR; - -#define ONE_BILLION 1000000000 -#ifdef DEBUG -#define DEBUGF(fmt,args...) printf(fmt ,##args) -#else -#define DEBUGF(fmt,args...) -#endif - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -#if defined(CONFIG_405GP) || defined(CONFIG_405CR) - -void get_sys_info (PPC4xx_SYS_INFO * sysInfo) -{ - unsigned long pllmr; - unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000); - uint pvr = get_pvr(); - unsigned long psr; - unsigned long m; - - /* - * Read PLL Mode register - */ - pllmr = mfdcr (CPC0_PLLMR); - - /* - * Read Pin Strapping register - */ - psr = mfdcr (CPC0_PSR); - - /* - * Determine FWD_DIV. - */ - sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29); - - /* - * Determine FBK_DIV. - */ - sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25); - if (sysInfo->pllFbkDiv == 0) { - sysInfo->pllFbkDiv = 16; - } - - /* - * Determine PLB_DIV. - */ - sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1; - - /* - * Determine PCI_DIV. - */ - sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1; - - /* - * Determine EXTBUS_DIV. - */ - sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2; - - /* - * Determine OPB_DIV. - */ - sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1; - - /* - * Check if PPC405GPr used (mask minor revision field) - */ - if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) { - /* - * Determine FWD_DIV B (only PPC405GPr with new mode strapping). - */ - sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK); - - /* - * Determine factor m depending on PLL feedback clock source - */ - if (!(psr & PSR_PCI_ASYNC_EN)) { - if (psr & PSR_NEW_MODE_EN) { - /* - * sync pci clock used as feedback (new mode) - */ - m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv; - } else { - /* - * sync pci clock used as feedback (legacy mode) - */ - m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv; - } - } else if (psr & PSR_NEW_MODE_EN) { - if (psr & PSR_PERCLK_SYNC_MODE_EN) { - /* - * PerClk used as feedback (new mode) - */ - m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv; - } else { - /* - * CPU clock used as feedback (new mode) - */ - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv; - } - } else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) { - /* - * PerClk used as feedback (legacy mode) - */ - m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv; - } else { - /* - * PLB clock used as feedback (legacy mode) - */ - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv; - } - - sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) / - (unsigned long long)sysClkPeriodPs; - sysInfo->freqProcessor = sysInfo->freqVCOHz / sysInfo->pllFwdDiv; - sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDivB * sysInfo->pllPlbDiv); - } else { - /* - * Check pllFwdDiv to see if running in bypass mode where the CPU speed - * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO - * to make sure it is within the proper range. - * spec: VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV - * Note freqVCO is calculated in MHz to avoid errors introduced by rounding. - */ - if (sysInfo->pllFwdDiv == 1) { - sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ; - sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv; - } else { - sysInfo->freqVCOHz = ( 1000000000000LL * - (unsigned long long)sysInfo->pllFwdDiv * - (unsigned long long)sysInfo->pllFbkDiv * - (unsigned long long)sysInfo->pllPlbDiv - ) / (unsigned long long)sysClkPeriodPs; - sysInfo->freqPLB = (ONE_BILLION / ((sysClkPeriodPs * 10) / - sysInfo->pllFbkDiv)) * 10000; - sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv; - } - } - - sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv; - sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv; - sysInfo->freqUART = sysInfo->freqProcessor; -} - - -/******************************************** - * get_PCI_freq - * return PCI bus freq in Hz - *********************************************/ -ulong get_PCI_freq (void) -{ - ulong val; - PPC4xx_SYS_INFO sys_info; - - get_sys_info (&sys_info); - val = sys_info.freqPLB / sys_info.pllPciDiv; - return val; -} - - -#elif defined(CONFIG_440) - -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ - defined(CONFIG_460SX) || defined(CONFIG_APM821XX) -static u8 pll_fwdv_multi_bits[] = { - /* values for: 1 - 16 */ - 0x00, 0x01, 0x0f, 0x04, 0x09, 0x0a, 0x0d, 0x0e, 0x03, 0x0c, - 0x05, 0x08, 0x07, 0x02, 0x0b, 0x06 -}; - -u32 get_cpr0_fwdv(unsigned long cpr_reg_fwdv) -{ - u32 index; - - for (index = 0; index < ARRAY_SIZE(pll_fwdv_multi_bits); index++) - if (cpr_reg_fwdv == (u32)pll_fwdv_multi_bits[index]) - return index + 1; - - return 0; -} - -static u8 pll_fbdv_multi_bits[] = { - /* values for: 1 - 100 */ - 0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4, - 0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb, - 0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96, - 0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde, - 0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb, - 0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91, - 0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b, - 0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95, - 0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4, - 0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc, - /* values for: 101 - 200 */ - 0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3, - 0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90, - 0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe, - 0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6, - 0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd, - 0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1, - 0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6, - 0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9, - 0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e, - 0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf, - /* values for: 201 - 255 */ - 0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae, - 0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2, - 0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2, - 0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98, - 0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81, - 0x03, 0x87, 0x0f, 0x9f, 0x3f /* END */ -}; - -u32 get_cpr0_fbdv(unsigned long cpr_reg_fbdv) -{ - u32 index; - - for (index = 0; index < ARRAY_SIZE(pll_fbdv_multi_bits); index++) - if (cpr_reg_fbdv == (u32)pll_fbdv_multi_bits[index]) - return index + 1; - - return 0; -} - -#if defined(CONFIG_APM821XX) - -void get_sys_info(sys_info_t *sysInfo) -{ - unsigned long plld; - unsigned long temp; - unsigned long mul; - unsigned long cpudv; - unsigned long plb2dv; - unsigned long ddr2dv; - - /* Calculate Forward divisor A and Feeback divisor */ - mfcpr(CPR0_PLLD, plld); - - temp = CPR0_PLLD_FWDVA(plld); - sysInfo->pllFwdDivA = get_cpr0_fwdv(temp); - - temp = CPR0_PLLD_FDV(plld); - sysInfo->pllFbkDiv = get_cpr0_fbdv(temp); - - /* Calculate OPB clock divisor */ - mfcpr(CPR0_OPBD, temp); - temp = CPR0_OPBD_OPBDV(temp); - sysInfo->pllOpbDiv = temp ? temp : 4; - - /* Calculate Peripheral clock divisor */ - mfcpr(CPR0_PERD, temp); - temp = CPR0_PERD_PERDV(temp); - sysInfo->pllExtBusDiv = temp ? temp : 4; - - /* Calculate CPU clock divisor */ - mfcpr(CPR0_CPUD, temp); - temp = CPR0_CPUD_CPUDV(temp); - cpudv = temp ? temp : 8; - - /* Calculate PLB2 clock divisor */ - mfcpr(CPR0_PLB2D, temp); - temp = CPR0_PLB2D_PLB2DV(temp); - plb2dv = temp ? temp : 4; - - /* Calculate DDR2 clock divisor */ - mfcpr(CPR0_DDR2D, temp); - temp = CPR0_DDR2D_DDR2DV(temp); - ddr2dv = temp ? temp : 4; - - /* Calculate 'M' based on feedback source */ - mfcpr(CPR0_PLLC, temp); - temp = CPR0_PLLC_SEL(temp); - if (temp == 0) { - /* PLL internal feedback */ - mul = sysInfo->pllFbkDiv; - } else { - /* PLL PerClk feedback */ - mul = sysInfo->pllFwdDivA * sysInfo->pllFbkDiv * cpudv - * plb2dv * 2 * sysInfo->pllOpbDiv * - sysInfo->pllExtBusDiv; - } - - /* Now calculate the individual clocks */ - sysInfo->freqVCOMhz = (mul * CONFIG_SYS_CLK_FREQ) + (mul >> 1); - sysInfo->freqProcessor = sysInfo->freqVCOMhz / - sysInfo->pllFwdDivA / cpudv; - sysInfo->freqPLB = sysInfo->freqVCOMhz / - sysInfo->pllFwdDivA / cpudv / plb2dv / 2; - sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv; - sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv; - sysInfo->freqDDR = sysInfo->freqVCOMhz / - sysInfo->pllFwdDivA / cpudv / ddr2dv / 2; - sysInfo->freqUART = sysInfo->freqPLB; -} - -#else -/* - * AMCC_TODO: verify this routine against latest EAS, cause stuff changed - * with latest EAS - */ -void get_sys_info (sys_info_t * sysInfo) -{ - unsigned long strp0; - unsigned long strp1; - unsigned long temp; - unsigned long m; - unsigned long plbedv0; - - /* Extract configured divisors */ - mfsdr(SDR0_SDSTP0, strp0); - mfsdr(SDR0_SDSTP1, strp1); - - temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 4); - sysInfo->pllFwdDivA = get_cpr0_fwdv(temp); - - temp = (strp0 & PLLSYS0_FWD_DIV_B_MASK); - sysInfo->pllFwdDivB = get_cpr0_fwdv(temp); - - temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 8; - sysInfo->pllFbkDiv = get_cpr0_fbdv(temp); - - temp = (strp1 & PLLSYS0_OPB_DIV_MASK) >> 26; - sysInfo->pllOpbDiv = temp ? temp : 4; - - /* AMCC_TODO: verify the SDR0_SDSTP1.PERDV0 value sysInfo->pllExtBusDiv */ - temp = (strp1 & PLLSYS0_PERCLK_DIV_MASK) >> 24; - sysInfo->pllExtBusDiv = temp ? temp : 4; - - temp = (strp1 & PLLSYS0_PLBEDV0_DIV_MASK) >> 29; - plbedv0 = temp ? temp: 8; - - /* Calculate 'M' based on feedback source */ - temp = (strp0 & PLLSYS0_SEL_MASK) >> 27; - if (temp == 0) { - /* PLL internal feedback */ - m = sysInfo->pllFbkDiv; - } else { - /* PLL PerClk feedback */ - m = sysInfo->pllFwdDivA * plbedv0 * sysInfo->pllOpbDiv * - sysInfo->pllExtBusDiv; - } - - /* Now calculate the individual clocks */ - sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1); - sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; - sysInfo->freqPLB = sysInfo->freqVCOMhz / sysInfo->pllFwdDivA / plbedv0; - sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv; - sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv; - sysInfo->freqDDR = sysInfo->freqPLB; - sysInfo->freqUART = sysInfo->freqPLB; - - return; -} -#endif - -#elif defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -void get_sys_info (sys_info_t *sysInfo) -{ - unsigned long temp; - unsigned long reg; - unsigned long lfdiv; - unsigned long m; - unsigned long prbdv0; - /* - WARNING: ASSUMES the following: - ENG=1 - PRADV0=1 - PRBDV0=1 - */ - - /* Decode CPR0_PLLD0 for divisors */ - mfcpr(CPR0_PLLD, reg); - temp = (reg & PLLD_FWDVA_MASK) >> 16; - sysInfo->pllFwdDivA = temp ? temp : 16; - temp = (reg & PLLD_FWDVB_MASK) >> 8; - sysInfo->pllFwdDivB = temp ? temp: 8 ; - temp = (reg & PLLD_FBDV_MASK) >> 24; - sysInfo->pllFbkDiv = temp ? temp : 32; - lfdiv = reg & PLLD_LFBDV_MASK; - - mfcpr(CPR0_OPBD0, reg); - temp = (reg & OPBDDV_MASK) >> 24; - sysInfo->pllOpbDiv = temp ? temp : 4; - - mfcpr(CPR0_PERD, reg); - temp = (reg & PERDV_MASK) >> 24; - sysInfo->pllExtBusDiv = temp ? temp : 8; - - mfcpr(CPR0_PRIMBD0, reg); - temp = (reg & PRBDV_MASK) >> 24; - prbdv0 = temp ? temp : 8; - - mfcpr(CPR0_SPCID, reg); - temp = (reg & SPCID_MASK) >> 24; - sysInfo->pllPciDiv = temp ? temp : 4; - - /* Calculate 'M' based on feedback source */ - mfsdr(SDR0_SDSTP0, reg); - temp = (reg & PLLSYS0_SEL_MASK) >> 27; - if (temp == 0) { /* PLL output */ - /* Figure which pll to use */ - mfcpr(CPR0_PLLC, reg); - temp = (reg & PLLC_SRC_MASK) >> 29; - if (!temp) /* PLLOUTA */ - m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA; - else /* PLLOUTB */ - m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB; - } - else if (temp == 1) /* CPU output */ - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA; - else /* PerClk */ - m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB; - - /* Now calculate the individual clocks */ - sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1); - sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; - sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0; - sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv; - sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv; - sysInfo->freqUART = sysInfo->freqPLB; - - /* Figure which timer source to use */ - if (mfspr(SPRN_CCR1) & 0x0080) { - /* External Clock, assume same as SYS_CLK */ - temp = sysInfo->freqProcessor / 2; /* Max extern clock speed */ - if (CONFIG_SYS_CLK_FREQ > temp) - sysInfo->freqTmrClk = temp; - else - sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ; - } - else /* Internal clock */ - sysInfo->freqTmrClk = sysInfo->freqProcessor; -} - -/******************************************** - * get_PCI_freq - * return PCI bus freq in Hz - *********************************************/ -ulong get_PCI_freq (void) -{ - sys_info_t sys_info; - get_sys_info (&sys_info); - return sys_info.freqPCI; -} - -#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) \ - && !defined(CONFIG_XILINX_440) -void get_sys_info (sys_info_t * sysInfo) -{ - unsigned long strp0; - unsigned long temp; - unsigned long m; - - /* Extract configured divisors */ - strp0 = mfdcr( CPC0_STRP0 ); - sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15); - sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12); - temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18; - sysInfo->pllFbkDiv = temp ? temp : 16; - sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10); - sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8); - - /* Calculate 'M' based on feedback source */ - if( strp0 & PLLSYS0_EXTSL_MASK ) - m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB; - else - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA; - - /* Now calculate the individual clocks */ - sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1); - sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; - sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB; - if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */ - sysInfo->freqPLB >>= 1; - sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv; - sysInfo->freqUART = sysInfo->freqPLB; -} -#else - -#if !defined(CONFIG_XILINX_440) -void get_sys_info (sys_info_t * sysInfo) -{ - unsigned long strp0; - unsigned long strp1; - unsigned long temp; - unsigned long temp1; - unsigned long lfdiv; - unsigned long m; - unsigned long prbdv0; - -#if defined(CONFIG_YUCCA) - unsigned long sys_freq; - unsigned long sys_per=0; - unsigned long msr; - unsigned long pci_clock_per; - unsigned long sdr_ddrpll; - - /*-------------------------------------------------------------------------+ - | Get the system clock period. - +-------------------------------------------------------------------------*/ - sys_per = determine_sysper(); - - msr = (mfmsr () & ~(MSR_EE)); /* disable interrupts */ - - /*-------------------------------------------------------------------------+ - | Calculate the system clock speed from the period. - +-------------------------------------------------------------------------*/ - sys_freq = (ONE_BILLION / sys_per) * 1000; -#endif - - /* Extract configured divisors */ - mfsdr( SDR0_SDSTP0,strp0 ); - mfsdr( SDR0_SDSTP1,strp1 ); - - temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8); - sysInfo->pllFwdDivA = temp ? temp : 16 ; - temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5); - sysInfo->pllFwdDivB = temp ? temp: 8 ; - temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12; - sysInfo->pllFbkDiv = temp ? temp : 32; - temp = (strp0 & PLLSYS0_OPB_DIV_MASK); - sysInfo->pllOpbDiv = temp ? temp : 4; - temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24; - sysInfo->pllExtBusDiv = temp ? temp : 4; - prbdv0 = (strp0 >> 2) & 0x7; - - /* Calculate 'M' based on feedback source */ - temp = (strp0 & PLLSYS0_SEL_MASK) >> 27; - temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26; - lfdiv = temp1 ? temp1 : 64; - if (temp == 0) { /* PLL output */ - /* Figure which pll to use */ - temp = (strp0 & PLLSYS0_SRC_MASK) >> 30; - if (!temp) - m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA; - else - m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB; - } - else if (temp == 1) /* CPU output */ - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA; - else /* PerClk */ - m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB; - - /* Now calculate the individual clocks */ -#if defined(CONFIG_YUCCA) - sysInfo->freqVCOMhz = (m * sys_freq) ; -#else - sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1); -#endif - sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; - sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0; - sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv; - -#if defined(CONFIG_YUCCA) - /* Determine PCI Clock Period */ - pci_clock_per = determine_pci_clock_per(); - sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000; - mfsdr(SDR0_DDR0, sdr_ddrpll); - sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); -#endif - - sysInfo->freqUART = sysInfo->freqPLB; -} - -#endif -#endif /* CONFIG_XILINX_440 */ - -#if defined(CONFIG_YUCCA) -unsigned long determine_sysper(void) -{ - unsigned int fpga_clocking_reg; - unsigned int master_clock_selection; - unsigned long master_clock_per = 0; - unsigned long fb_div_selection; - unsigned int vco_div_reg_value; - unsigned long vco_div_selection; - unsigned long sys_per = 0; - int extClkVal; - - /*-------------------------------------------------------------------------+ - | Read FPGA reg 0 and reg 1 to get FPGA reg information - +-------------------------------------------------------------------------*/ - fpga_clocking_reg = in16(FPGA_REG16); - - - /* Determine Master Clock Source Selection */ - master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK; - - switch(master_clock_selection) { - case FPGA_REG16_MASTER_CLK_66_66: - master_clock_per = PERIOD_66_66MHZ; - break; - case FPGA_REG16_MASTER_CLK_50: - master_clock_per = PERIOD_50_00MHZ; - break; - case FPGA_REG16_MASTER_CLK_33_33: - master_clock_per = PERIOD_33_33MHZ; - break; - case FPGA_REG16_MASTER_CLK_25: - master_clock_per = PERIOD_25_00MHZ; - break; - case FPGA_REG16_MASTER_CLK_EXT: - if ((extClkVal==EXTCLK_33_33) - && (extClkVal==EXTCLK_50) - && (extClkVal==EXTCLK_66_66) - && (extClkVal==EXTCLK_83)) { - /* calculate master clock period from external clock value */ - master_clock_per=(ONE_BILLION/extClkVal) * 1000; - } else { - /* Unsupported */ - DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__); - hang(); - } - break; - default: - /* Unsupported */ - DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__); - hang(); - break; - } - - /* Determine FB divisors values */ - if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) { - if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW) - fb_div_selection = FPGA_FB_DIV_6; - else - fb_div_selection = FPGA_FB_DIV_12; - } else { - if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW) - fb_div_selection = FPGA_FB_DIV_10; - else - fb_div_selection = FPGA_FB_DIV_20; - } - - /* Determine VCO divisors values */ - vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK; - - switch(vco_div_reg_value) { - case FPGA_REG16_VCO_DIV_4: - vco_div_selection = FPGA_VCO_DIV_4; - break; - case FPGA_REG16_VCO_DIV_6: - vco_div_selection = FPGA_VCO_DIV_6; - break; - case FPGA_REG16_VCO_DIV_8: - vco_div_selection = FPGA_VCO_DIV_8; - break; - case FPGA_REG16_VCO_DIV_10: - default: - vco_div_selection = FPGA_VCO_DIV_10; - break; - } - - if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) { - switch(master_clock_per) { - case PERIOD_25_00MHZ: - if (fb_div_selection == FPGA_FB_DIV_12) { - if (vco_div_selection == FPGA_VCO_DIV_4) - sys_per = PERIOD_75_00MHZ; - if (vco_div_selection == FPGA_VCO_DIV_6) - sys_per = PERIOD_50_00MHZ; - } - break; - case PERIOD_33_33MHZ: - if (fb_div_selection == FPGA_FB_DIV_6) { - if (vco_div_selection == FPGA_VCO_DIV_4) - sys_per = PERIOD_50_00MHZ; - if (vco_div_selection == FPGA_VCO_DIV_6) - sys_per = PERIOD_33_33MHZ; - } - if (fb_div_selection == FPGA_FB_DIV_10) { - if (vco_div_selection == FPGA_VCO_DIV_4) - sys_per = PERIOD_83_33MHZ; - if (vco_div_selection == FPGA_VCO_DIV_10) - sys_per = PERIOD_33_33MHZ; - } - if (fb_div_selection == FPGA_FB_DIV_12) { - if (vco_div_selection == FPGA_VCO_DIV_4) - sys_per = PERIOD_100_00MHZ; - if (vco_div_selection == FPGA_VCO_DIV_6) - sys_per = PERIOD_66_66MHZ; - if (vco_div_selection == FPGA_VCO_DIV_8) - sys_per = PERIOD_50_00MHZ; - } - break; - case PERIOD_50_00MHZ: - if (fb_div_selection == FPGA_FB_DIV_6) { - if (vco_div_selection == FPGA_VCO_DIV_4) - sys_per = PERIOD_75_00MHZ; - if (vco_div_selection == FPGA_VCO_DIV_6) - sys_per = PERIOD_50_00MHZ; - } - if (fb_div_selection == FPGA_FB_DIV_10) { - if (vco_div_selection == FPGA_VCO_DIV_6) - sys_per = PERIOD_83_33MHZ; - if (vco_div_selection == FPGA_VCO_DIV_10) - sys_per = PERIOD_50_00MHZ; - } - if (fb_div_selection == FPGA_FB_DIV_12) { - if (vco_div_selection == FPGA_VCO_DIV_6) - sys_per = PERIOD_100_00MHZ; - if (vco_div_selection == FPGA_VCO_DIV_8) - sys_per = PERIOD_75_00MHZ; - } - break; - case PERIOD_66_66MHZ: - if (fb_div_selection == FPGA_FB_DIV_6) { - if (vco_div_selection == FPGA_VCO_DIV_4) - sys_per = PERIOD_100_00MHZ; - if (vco_div_selection == FPGA_VCO_DIV_6) - sys_per = PERIOD_66_66MHZ; - if (vco_div_selection == FPGA_VCO_DIV_8) - sys_per = PERIOD_50_00MHZ; - } - if (fb_div_selection == FPGA_FB_DIV_10) { - if (vco_div_selection == FPGA_VCO_DIV_8) - sys_per = PERIOD_83_33MHZ; - if (vco_div_selection == FPGA_VCO_DIV_10) - sys_per = PERIOD_66_66MHZ; - } - if (fb_div_selection == FPGA_FB_DIV_12) { - if (vco_div_selection == FPGA_VCO_DIV_8) - sys_per = PERIOD_100_00MHZ; - } - break; - default: - break; - } - - if (sys_per == 0) { - /* Other combinations are not supported */ - DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__); - hang(); - } - } else { - /* calcul system clock without cheking */ - /* if engineering option clock no check is selected */ - /* sys_per = master_clock_per * vco_div_selection / fb_div_selection */ - sys_per = (master_clock_per/fb_div_selection) * vco_div_selection; - } - - return(sys_per); -} - -/*-------------------------------------------------------------------------+ -| determine_pci_clock_per. -+-------------------------------------------------------------------------*/ -unsigned long determine_pci_clock_per(void) -{ - unsigned long pci_clock_selection, pci_period; - - /*-------------------------------------------------------------------------+ - | Read FPGA reg 6 to get PCI 0 FPGA reg information - +-------------------------------------------------------------------------*/ - pci_clock_selection = in16(FPGA_REG16); /* was reg6 averifier */ - - - pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK; - - switch (pci_clock_selection) { - case FPGA_REG16_PCI0_CLK_133_33: - pci_period = PERIOD_133_33MHZ; - break; - case FPGA_REG16_PCI0_CLK_100: - pci_period = PERIOD_100_00MHZ; - break; - case FPGA_REG16_PCI0_CLK_66_66: - pci_period = PERIOD_66_66MHZ; - break; - default: - pci_period = PERIOD_33_33MHZ;; - break; - } - - return(pci_period); -} -#endif - -#elif defined(CONFIG_XILINX_405) -extern void get_sys_info (sys_info_t * sysInfo); -extern ulong get_PCI_freq (void); - -#elif defined(CONFIG_AP1000) -void get_sys_info (sys_info_t * sysInfo) -{ - sysInfo->freqProcessor = 240 * 1000 * 1000; - sysInfo->freqPLB = 80 * 1000 * 1000; - sysInfo->freqPCI = 33 * 1000 * 1000; -} - -#elif defined(CONFIG_405) - -void get_sys_info (sys_info_t * sysInfo) -{ - sysInfo->freqVCOMhz=3125000; - sysInfo->freqProcessor=12*1000*1000; - sysInfo->freqPLB=50*1000*1000; - sysInfo->freqPCI=66*1000*1000; -} - -#elif defined(CONFIG_405EP) -void get_sys_info (PPC4xx_SYS_INFO * sysInfo) -{ - unsigned long pllmr0; - unsigned long pllmr1; - unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000); - unsigned long m; - unsigned long pllmr0_ccdv; - - /* - * Read PLL Mode registers - */ - pllmr0 = mfdcr (CPC0_PLLMR0); - pllmr1 = mfdcr (CPC0_PLLMR1); - - /* - * Determine forward divider A - */ - sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16); - - /* - * Determine forward divider B (should be equal to A) - */ - sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12); - - /* - * Determine FBK_DIV. - */ - sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20); - if (sysInfo->pllFbkDiv == 0) - sysInfo->pllFbkDiv = 16; - - /* - * Determine PLB_DIV. - */ - sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1; - - /* - * Determine PCI_DIV. - */ - sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1; - - /* - * Determine EXTBUS_DIV. - */ - sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2; - - /* - * Determine OPB_DIV. - */ - sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1; - - /* - * Determine the M factor - */ - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB; - - /* - * Determine VCO clock frequency - */ - sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) / - (unsigned long long)sysClkPeriodPs; - - /* - * Determine CPU clock frequency - */ - pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1; - if (pllmr1 & PLLMR1_SSCS_MASK) { - /* - * This is true if FWDVA == FWDVB: - * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) - * / pllmr0_ccdv; - */ - sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB) - / sysInfo->pllFwdDiv / pllmr0_ccdv; - } else { - sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv; - } - - /* - * Determine PLB clock frequency - */ - sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv; - - sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv; - - sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv; - - sysInfo->freqUART = sysInfo->freqProcessor * pllmr0_ccdv; -} - - -/******************************************** - * get_PCI_freq - * return PCI bus freq in Hz - *********************************************/ -ulong get_PCI_freq (void) -{ - ulong val; - PPC4xx_SYS_INFO sys_info; - - get_sys_info (&sys_info); - val = sys_info.freqPLB / sys_info.pllPciDiv; - return val; -} - -#elif defined(CONFIG_405EZ) -void get_sys_info (PPC4xx_SYS_INFO * sysInfo) -{ - unsigned long cpr_plld; - unsigned long cpr_pllc; - unsigned long cpr_primad; - unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000); - unsigned long primad_cpudv; - unsigned long m; - unsigned long plloutb; - - /* - * Read PLL Mode registers - */ - mfcpr(CPR0_PLLD, cpr_plld); - mfcpr(CPR0_PLLC, cpr_pllc); - - /* - * Determine forward divider A - */ - sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16); - - /* - * Determine forward divider B - */ - sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8); - if (sysInfo->pllFwdDivB == 0) - sysInfo->pllFwdDivB = 8; - - /* - * Determine FBK_DIV. - */ - sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24); - if (sysInfo->pllFbkDiv == 0) - sysInfo->pllFbkDiv = 256; - - /* - * Read CPR_PRIMAD register - */ - mfcpr(CPR0_PRIMAD, cpr_primad); - - /* - * Determine PLB_DIV. - */ - sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16); - if (sysInfo->pllPlbDiv == 0) - sysInfo->pllPlbDiv = 16; - - /* - * Determine EXTBUS_DIV. - */ - sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK); - if (sysInfo->pllExtBusDiv == 0) - sysInfo->pllExtBusDiv = 16; - - /* - * Determine OPB_DIV. - */ - sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8); - if (sysInfo->pllOpbDiv == 0) - sysInfo->pllOpbDiv = 16; - - /* - * Determine the M factor - */ - if (cpr_pllc & PLLC_SRC_MASK) - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB; - else - m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv; - - /* - * Determine VCO clock frequency - */ - sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) / - (unsigned long long)sysClkPeriodPs; - - /* - * Determine CPU clock frequency - */ - primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24); - if (primad_cpudv == 0) - primad_cpudv = 16; - - sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) / - sysInfo->pllFwdDiv / primad_cpudv; - - /* - * Determine PLB clock frequency - */ - sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) / - sysInfo->pllFwdDiv / sysInfo->pllPlbDiv; - - sysInfo->freqOPB = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / - sysInfo->pllOpbDiv; - - sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / - sysInfo->pllExtBusDiv; - - plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ? - sysInfo->pllFwdDivB : sysInfo->pllFwdDiv) * sysInfo->pllFbkDiv) / - sysInfo->pllFwdDivB); - sysInfo->freqUART = plloutb; -} - -#elif defined(CONFIG_405EX) - -/* - * TODO: We need to get the CPR registers and calculate these values correctly!!!! - * We need the specs!!!! - */ -static unsigned char get_fbdv(unsigned char index) -{ - unsigned char ret = 0; - /* This is table should be 256 bytes. - * Only take first 52 values. - */ - unsigned char fbdv_tb[] = { - 0x00, 0xff, 0x7f, 0xfd, - 0x7a, 0xf5, 0x6a, 0xd5, - 0x2a, 0xd4, 0x29, 0xd3, - 0x26, 0xcc, 0x19, 0xb3, - 0x67, 0xce, 0x1d, 0xbb, - 0x77, 0xee, 0x5d, 0xba, - 0x74, 0xe9, 0x52, 0xa5, - 0x4b, 0x96, 0x2c, 0xd8, - 0x31, 0xe3, 0x46, 0x8d, - 0x1b, 0xb7, 0x6f, 0xde, - 0x3d, 0xfb, 0x76, 0xed, - 0x5a, 0xb5, 0x6b, 0xd6, - 0x2d, 0xdb, 0x36, 0xec, - - }; - - if ((index & 0x7f) == 0) - return 1; - while (ret < sizeof (fbdv_tb)) { - if (fbdv_tb[ret] == index) - break; - ret++; - } - ret++; - - return ret; -} - -#define PLL_FBK_PLL_LOCAL 0 -#define PLL_FBK_CPU 1 -#define PLL_FBK_PERCLK 5 - -void get_sys_info (sys_info_t * sysInfo) -{ - unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000); - unsigned long m = 1; - unsigned int tmp; - unsigned char fwdva[16] = { - 1, 2, 14, 9, 4, 11, 16, 13, - 12, 5, 6, 15, 10, 7, 8, 3, - }; - unsigned char sel, cpudv0, plb2xDiv; - - mfcpr(CPR0_PLLD, tmp); - - /* - * Determine forward divider A - */ - sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)]; /* FWDVA */ - - /* - * Determine FBK_DIV. - */ - sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */ - - /* - * Determine PLBDV0 - */ - sysInfo->pllPlbDiv = 2; - - /* - * Determine PERDV0 - */ - mfcpr(CPR0_PERD, tmp); - tmp = (tmp >> 24) & 0x03; - sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp; - - /* - * Determine OPBDV0 - */ - mfcpr(CPR0_OPBD0, tmp); - tmp = (tmp >> 24) & 0x03; - sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp; - - /* Determine PLB2XDV0 */ - mfcpr(CPR0_PLBD, tmp); - tmp = (tmp >> 16) & 0x07; - plb2xDiv = (tmp == 0) ? 8 : tmp; - - /* Determine CPUDV0 */ - mfcpr(CPR0_CPUD, tmp); - tmp = (tmp >> 24) & 0x07; - cpudv0 = (tmp == 0) ? 8 : tmp; - - /* Determine SEL(5:7) in CPR0_PLLC */ - mfcpr(CPR0_PLLC, tmp); - sel = (tmp >> 24) & 0x07; - - /* - * Determine the M factor - * PLL local: M = FBDV - * CPU clock: M = FBDV * FWDVA * CPUDV0 - * PerClk : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0 - * - */ - switch (sel) { - case PLL_FBK_CPU: - m = sysInfo->pllFwdDiv * cpudv0; - break; - case PLL_FBK_PERCLK: - m = sysInfo->pllFwdDiv * plb2xDiv * 2 - * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv; - break; - case PLL_FBK_PLL_LOCAL: - break; - default: - printf("%s unknown m\n", __FUNCTION__); - return; - - } - m *= sysInfo->pllFbkDiv; - - /* - * Determine VCO clock frequency - */ - sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) / - (unsigned long long)sysClkPeriodPs; - - /* - * Determine CPU clock frequency - */ - sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0); - - /* - * Determine PLB clock frequency, ddr1x should be the same - */ - sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2); - sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqDDR = sysInfo->freqPLB; - sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv; - sysInfo->freqUART = sysInfo->freqPLB; -} - -#endif - -int get_clocks (void) -{ -#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ - defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_405EX) || defined(CONFIG_405) || \ - defined(CONFIG_440) - sys_info_t sys_info; - - get_sys_info (&sys_info); - gd->cpu_clk = sys_info.freqProcessor; - gd->bus_clk = sys_info.freqPLB; - -#endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */ - -#ifdef CONFIG_IOP480 - gd->cpu_clk = 66000000; - gd->bus_clk = 66000000; -#endif - return (0); -} - - -/******************************************** - * get_bus_freq - * return PLB bus freq in Hz - *********************************************/ -ulong get_bus_freq (ulong dummy) -{ - ulong val; - -#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ - defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_405EX) || defined(CONFIG_405) || \ - defined(CONFIG_440) - sys_info_t sys_info; - - get_sys_info (&sys_info); - val = sys_info.freqPLB; - -#elif defined(CONFIG_IOP480) - - val = 66; - -#else -# error get_bus_freq() not implemented -#endif - - return val; -} - -#if !defined(CONFIG_IOP480) -ulong get_OPB_freq (void) -{ - PPC4xx_SYS_INFO sys_info; - - get_sys_info (&sys_info); - - return sys_info.freqOPB; -} -#endif diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S deleted file mode 100644 index 2218508..0000000 --- a/arch/powerpc/cpu/ppc4xx/start.S +++ /dev/null @@ -1,2182 +0,0 @@ -/* - * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> - * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> - * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de> - * Copyright (C) 2007 Stefan Roese <sr@denx.de>, DENX Software Engineering - * Copyright (c) 2008 Nuovation System Designs, LLC - * Grant Erickson <gerickson@nuovations.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -/*------------------------------------------------------------------------------+ - * 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 - *------------------------------------------------------------------------------- - */ - -/* - * Startup code for IBM/AMCC PowerPC 4xx (PPC4xx) based boards - * - * The following description only applies to the NOR flash style booting. - * NAND booting is different. For more details about NAND booting on 4xx - * take a look at doc/README.nand-boot-ppc440. - * - * The CPU starts at address 0xfffffffc (last word in the address space). - * The U-Boot image therefore has to be located in the "upper" area of the - * flash (e.g. 512MiB - 0xfff80000 ... 0xffffffff). The default value for - * the boot chip-select (CS0) is quite big and covers this area. On the - * 405EX this is for example 0xffe00000 ... 0xffffffff. U-Boot will - * reconfigure this CS0 (and other chip-selects as well when configured - * this way) in the boot process to the "correct" values matching the - * board layout. - */ - -#include <asm-offsets.h> -#include <config.h> -#include <asm/ppc4xx.h> -#include <timestamp.h> -#include <version.h> - -#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ - -#include <ppc_asm.tmpl> -#include <ppc_defs.h> - -#include <asm/cache.h> -#include <asm/mmu.h> -#include <asm/ppc4xx-isram.h> - -#ifndef CONFIG_IDENT_STRING -#define CONFIG_IDENT_STRING "" -#endif - -#ifdef CONFIG_SYS_INIT_DCACHE_CS -# if (CONFIG_SYS_INIT_DCACHE_CS == 0) -# define PBxAP PB1AP -# define PBxCR PB0CR -# if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR)) -# define PBxAP_VAL CONFIG_SYS_EBC_PB0AP -# define PBxCR_VAL CONFIG_SYS_EBC_PB0CR -# endif -# endif -# if (CONFIG_SYS_INIT_DCACHE_CS == 1) -# define PBxAP PB1AP -# define PBxCR PB1CR -# if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR)) -# define PBxAP_VAL CONFIG_SYS_EBC_PB1AP -# define PBxCR_VAL CONFIG_SYS_EBC_PB1CR -# endif -# endif -# if (CONFIG_SYS_INIT_DCACHE_CS == 2) -# define PBxAP PB2AP -# define PBxCR PB2CR -# if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR)) -# define PBxAP_VAL CONFIG_SYS_EBC_PB2AP -# define PBxCR_VAL CONFIG_SYS_EBC_PB2CR -# endif -# endif -# if (CONFIG_SYS_INIT_DCACHE_CS == 3) -# define PBxAP PB3AP -# define PBxCR PB3CR -# if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR)) -# define PBxAP_VAL CONFIG_SYS_EBC_PB3AP -# define PBxCR_VAL CONFIG_SYS_EBC_PB3CR -# endif -# endif -# if (CONFIG_SYS_INIT_DCACHE_CS == 4) -# define PBxAP PB4AP -# define PBxCR PB4CR -# if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR)) -# define PBxAP_VAL CONFIG_SYS_EBC_PB4AP -# define PBxCR_VAL CONFIG_SYS_EBC_PB4CR -# endif -# endif -# if (CONFIG_SYS_INIT_DCACHE_CS == 5) -# define PBxAP PB5AP -# define PBxCR PB5CR -# if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR)) -# define PBxAP_VAL CONFIG_SYS_EBC_PB5AP -# define PBxCR_VAL CONFIG_SYS_EBC_PB5CR -# endif -# endif -# if (CONFIG_SYS_INIT_DCACHE_CS == 6) -# define PBxAP PB6AP -# define PBxCR PB6CR -# if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR)) -# define PBxAP_VAL CONFIG_SYS_EBC_PB6AP -# define PBxCR_VAL CONFIG_SYS_EBC_PB6CR -# endif -# endif -# if (CONFIG_SYS_INIT_DCACHE_CS == 7) -# define PBxAP PB7AP -# define PBxCR PB7CR -# if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR)) -# define PBxAP_VAL CONFIG_SYS_EBC_PB7AP -# define PBxCR_VAL CONFIG_SYS_EBC_PB7CR -# endif -# endif -# ifndef PBxAP_VAL -# define PBxAP_VAL 0 -# endif -# ifndef PBxCR_VAL -# define PBxCR_VAL 0 -# endif -/* - * Memory Bank x (nothingness) initialization CONFIG_SYS_INIT_RAM_ADDR + 64 MiB - * used as temporary stack pointer for the primordial stack - */ -# ifndef CONFIG_SYS_INIT_DCACHE_PBxAR -# define CONFIG_SYS_INIT_DCACHE_PBxAR (EBC_BXAP_BME_DISABLED | \ - EBC_BXAP_TWT_ENCODE(7) | \ - EBC_BXAP_BCE_DISABLE | \ - EBC_BXAP_BCT_2TRANS | \ - EBC_BXAP_CSN_ENCODE(0) | \ - EBC_BXAP_OEN_ENCODE(0) | \ - EBC_BXAP_WBN_ENCODE(0) | \ - EBC_BXAP_WBF_ENCODE(0) | \ - EBC_BXAP_TH_ENCODE(2) | \ - EBC_BXAP_RE_DISABLED | \ - EBC_BXAP_SOR_NONDELAYED | \ - EBC_BXAP_BEM_WRITEONLY | \ - EBC_BXAP_PEN_DISABLED) -# endif /* CONFIG_SYS_INIT_DCACHE_PBxAR */ -# ifndef CONFIG_SYS_INIT_DCACHE_PBxCR -# define CONFIG_SYS_INIT_DCACHE_PBxCR (EBC_BXCR_BAS_ENCODE(CONFIG_SYS_INIT_RAM_ADDR) | \ - EBC_BXCR_BS_64MB | \ - EBC_BXCR_BU_RW | \ - EBC_BXCR_BW_16BIT) -# endif /* CONFIG_SYS_INIT_DCACHE_PBxCR */ -# ifndef CONFIG_SYS_INIT_RAM_PATTERN -# define CONFIG_SYS_INIT_RAM_PATTERN 0xDEADDEAD -# endif -#endif /* CONFIG_SYS_INIT_DCACHE_CS */ - -#if (defined(CONFIG_SYS_INIT_RAM_DCACHE) && (CONFIG_SYS_INIT_RAM_SIZE > (4 << 10))) -#error Only 4k of init-ram is supported - please adjust CONFIG_SYS_INIT_RAM_SIZE! -#endif - -/* - * Unless otherwise overriden, enable two 128MB cachable instruction regions - * at CONFIG_SYS_SDRAM_BASE and another 128MB cacheable instruction region covering - * NOR flash at CONFIG_SYS_FLASH_BASE. Disable all cacheable data regions. - */ -#if !defined(CONFIG_SYS_FLASH_BASE) -/* If not already defined, set it to the "last" 128MByte region */ -# define CONFIG_SYS_FLASH_BASE 0xf8000000 -#endif -#if !defined(CONFIG_SYS_ICACHE_SACR_VALUE) -# define CONFIG_SYS_ICACHE_SACR_VALUE \ - (PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + ( 0 << 20)) | \ - PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + (128 << 20)) | \ - PPC_128MB_SACR_VALUE(CONFIG_SYS_FLASH_BASE)) -#endif /* !defined(CONFIG_SYS_ICACHE_SACR_VALUE) */ - -#if !defined(CONFIG_SYS_DCACHE_SACR_VALUE) -# define CONFIG_SYS_DCACHE_SACR_VALUE \ - (0x00000000) -#endif /* !defined(CONFIG_SYS_DCACHE_SACR_VALUE) */ - -#if !defined(CONFIG_SYS_TLB_FOR_BOOT_FLASH) -#define CONFIG_SYS_TLB_FOR_BOOT_FLASH 0 /* use TLB 0 as default */ -#endif - -#define function_prolog(func_name) .text; \ - .align 2; \ - .globl func_name; \ - func_name: -#define function_epilog(func_name) .type func_name,@function; \ - .size func_name,.-func_name - -/* We don't want the MMU yet. -*/ -#undef MSR_KERNEL -#define MSR_KERNEL ( MSR_ME ) /* Machine Check */ - - - .extern ext_bus_cntlr_init -#ifdef CONFIG_NAND_U_BOOT - .extern reconfig_tlb0 -#endif - -/* - * Set up GOT: Global Offset Table - * - * Use r12 to access the GOT - */ -#if !defined(CONFIG_NAND_SPL) - START_GOT - GOT_ENTRY(_GOT2_TABLE_) - GOT_ENTRY(_FIXUP_TABLE_) - - GOT_ENTRY(_start) - GOT_ENTRY(_start_of_vectors) - GOT_ENTRY(_end_of_vectors) - GOT_ENTRY(transfer_to_handler) - - GOT_ENTRY(__init_end) - GOT_ENTRY(_end) - GOT_ENTRY(__bss_start) - END_GOT -#endif /* CONFIG_NAND_SPL */ - -#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) - /* - * NAND U-Boot image is started from offset 0 - */ - .text -#if defined(CONFIG_440) - bl reconfig_tlb0 -#endif - GET_GOT - bl cpu_init_f /* run low-level CPU init code (from Flash) */ - bl board_init_f - /* NOTREACHED - board_init_f() does not return */ -#endif - -#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_BOOT_FROM_XMD) - /* - * 4xx RAM-booting U-Boot image is started from offset 0 - */ - .text - bl _start_440 -#endif - -/* - * 440 Startup -- on reset only the top 4k of the effective - * address space is mapped in by an entry in the instruction - * and data shadow TLB. The .bootpg section is located in the - * top 4k & does only what's necessary to map in the the rest - * of the boot rom. Once the boot rom is mapped in we can - * proceed with normal startup. - * - * NOTE: CS0 only covers the top 2MB of the effective address - * space after reset. - */ - -#if defined(CONFIG_440) -#if !defined(CONFIG_NAND_SPL) - .section .bootpg,"ax" -#endif - .globl _start_440 - -/**************************************************************************/ -_start_440: - /*--------------------------------------------------------------------+ - | 440EPX BUP Change - Hardware team request - +--------------------------------------------------------------------*/ -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - sync - nop - nop -#endif - /*----------------------------------------------------------------+ - | Core bug fix. Clear the esr - +-----------------------------------------------------------------*/ - li r0,0 - mtspr SPRN_ESR,r0 - /*----------------------------------------------------------------*/ - /* Clear and set up some registers. */ - /*----------------------------------------------------------------*/ - iccci r0,r0 /* NOTE: operands not used for 440 */ - dccci r0,r0 /* NOTE: operands not used for 440 */ - sync - li r0,0 - mtspr SPRN_SRR0,r0 - mtspr SPRN_SRR1,r0 - mtspr SPRN_CSRR0,r0 - mtspr SPRN_CSRR1,r0 - /* NOTE: 440GX adds machine check status regs */ -#if defined(CONFIG_440) && !defined(CONFIG_440GP) - mtspr SPRN_MCSRR0,r0 - mtspr SPRN_MCSRR1,r0 - mfspr r1,SPRN_MCSR - mtspr SPRN_MCSR,r1 -#endif - - /*----------------------------------------------------------------*/ - /* CCR0 init */ - /*----------------------------------------------------------------*/ - /* Disable store gathering & broadcast, guarantee inst/data - * cache block touch, force load/store alignment - * (see errata 1.12: 440_33) - */ - lis r1,0x0030 /* store gathering & broadcast disable */ - ori r1,r1,0x6000 /* cache touch */ - mtspr SPRN_CCR0,r1 - - /*----------------------------------------------------------------*/ - /* Initialize debug */ - /*----------------------------------------------------------------*/ - mfspr r1,SPRN_DBCR0 - andis. r1, r1, 0x8000 /* test DBCR0[EDM] bit */ - bne skip_debug_init /* if set, don't clear debug register */ - mfspr r1,SPRN_CCR0 - ori r1,r1,CCR0_DTB@l /* Disable Trace Broadcast */ - mtspr SPRN_CCR0,r1 - mtspr SPRN_DBCR0,r0 - mtspr SPRN_DBCR1,r0 - mtspr SPRN_DBCR2,r0 - mtspr SPRN_IAC1,r0 - mtspr SPRN_IAC2,r0 - mtspr SPRN_IAC3,r0 - mtspr SPRN_DAC1,r0 - mtspr SPRN_DAC2,r0 - mtspr SPRN_DVC1,r0 - mtspr SPRN_DVC2,r0 - - mfspr r1,SPRN_DBSR - mtspr SPRN_DBSR,r1 /* Clear all valid bits */ -skip_debug_init: - -#if defined (CONFIG_440SPE) - /*----------------------------------------------------------------+ - | Initialize Core Configuration Reg1. - | a. ICDPEI: Record even parity. Normal operation. - | b. ICTPEI: Record even parity. Normal operation. - | c. DCTPEI: Record even parity. Normal operation. - | d. DCDPEI: Record even parity. Normal operation. - | e. DCUPEI: Record even parity. Normal operation. - | f. DCMPEI: Record even parity. Normal operation. - | g. FCOM: Normal operation - | h. MMUPEI: Record even parity. Normal operation. - | i. FFF: Flush only as much data as necessary. - | j. TCS: Timebase increments from CPU clock. - +-----------------------------------------------------------------*/ - li r0,0 - mtspr SPRN_CCR1, r0 - - /*----------------------------------------------------------------+ - | Reset the timebase. - | The previous write to CCR1 sets the timebase source. - +-----------------------------------------------------------------*/ - mtspr SPRN_TBWL, r0 - mtspr SPRN_TBWU, r0 -#endif - - /*----------------------------------------------------------------*/ - /* Setup interrupt vectors */ - /*----------------------------------------------------------------*/ - mtspr SPRN_IVPR,r0 /* Vectors start at 0x0000_0000 */ - li r1,0x0100 - mtspr SPRN_IVOR0,r1 /* Critical input */ - li r1,0x0200 - mtspr SPRN_IVOR1,r1 /* Machine check */ - li r1,0x0300 - mtspr SPRN_IVOR2,r1 /* Data storage */ - li r1,0x0400 - mtspr SPRN_IVOR3,r1 /* Instruction storage */ - li r1,0x0500 - mtspr SPRN_IVOR4,r1 /* External interrupt */ - li r1,0x0600 - mtspr SPRN_IVOR5,r1 /* Alignment */ - li r1,0x0700 - mtspr SPRN_IVOR6,r1 /* Program check */ - li r1,0x0800 - mtspr SPRN_IVOR7,r1 /* Floating point unavailable */ - li r1,0x0c00 - mtspr SPRN_IVOR8,r1 /* System call */ - li r1,0x0a00 - mtspr SPRN_IVOR9,r1 /* Auxiliary Processor unavailable */ - li r1,0x0900 - mtspr SPRN_IVOR10,r1 /* Decrementer */ - li r1,0x1300 - mtspr SPRN_IVOR13,r1 /* Data TLB error */ - li r1,0x1400 - mtspr SPRN_IVOR14,r1 /* Instr TLB error */ - li r1,0x2000 - mtspr SPRN_IVOR15,r1 /* Debug */ - - /*----------------------------------------------------------------*/ - /* Configure cache regions */ - /*----------------------------------------------------------------*/ - mtspr SPRN_INV0,r0 - mtspr SPRN_INV1,r0 - mtspr SPRN_INV2,r0 - mtspr SPRN_INV3,r0 - mtspr SPRN_DNV0,r0 - mtspr SPRN_DNV1,r0 - mtspr SPRN_DNV2,r0 - mtspr SPRN_DNV3,r0 - mtspr SPRN_ITV0,r0 - mtspr SPRN_ITV1,r0 - mtspr SPRN_ITV2,r0 - mtspr SPRN_ITV3,r0 - mtspr SPRN_DTV0,r0 - mtspr SPRN_DTV1,r0 - mtspr SPRN_DTV2,r0 - mtspr SPRN_DTV3,r0 - - /*----------------------------------------------------------------*/ - /* Cache victim limits */ - /*----------------------------------------------------------------*/ - /* floors 0, ceiling max to use the entire cache -- nothing locked - */ - lis r1,0x0001 - ori r1,r1,0xf800 - mtspr SPRN_IVLIM,r1 - mtspr SPRN_DVLIM,r1 - - /*----------------------------------------------------------------+ - |Initialize MMUCR[STID] = 0. - +-----------------------------------------------------------------*/ - mfspr r0,SPRN_MMUCR - addis r1,0,0xFFFF - ori r1,r1,0xFF00 - and r0,r0,r1 - mtspr SPRN_MMUCR,r0 - - /*----------------------------------------------------------------*/ - /* Clear all TLB entries -- TID = 0, TS = 0 */ - /*----------------------------------------------------------------*/ - addis r0,0,0x0000 -#ifdef CONFIG_SYS_RAMBOOT - li r4,0 /* Start with TLB #0 */ -#else - li r4,1 /* Start with TLB #1 */ -#endif - li r1,64 /* 64 TLB entries */ - sub r1,r1,r4 /* calculate last TLB # */ - mtctr r1 -rsttlb: -#ifdef CONFIG_SYS_RAMBOOT - tlbre r3,r4,0 /* Read contents from TLB word #0 to get EPN */ - rlwinm. r3,r3,0,0xfffffc00 /* Mask EPN */ - beq tlbnxt /* Skip EPN=0 TLB, this is the SDRAM TLB */ -#endif - tlbwe r0,r4,0 /* Invalidate all entries (V=0)*/ - tlbwe r0,r4,1 - tlbwe r0,r4,2 -tlbnxt: addi r4,r4,1 /* Next TLB */ - bdnz rsttlb - - /*----------------------------------------------------------------*/ - /* TLB entry setup -- step thru tlbtab */ - /*----------------------------------------------------------------*/ -#if defined(CONFIG_440SPE_REVA) - /*----------------------------------------------------------------*/ - /* We have different TLB tables for revA and rev B of 440SPe */ - /*----------------------------------------------------------------*/ - mfspr r1, PVR - lis r0,0x5342 - ori r0,r0,0x1891 - cmpw r7,r1,r0 - bne r7,..revA - bl tlbtabB - b ..goon -..revA: - bl tlbtabA -..goon: -#else - bl tlbtab /* Get tlbtab pointer */ -#endif - mr r5,r0 - li r1,0x003f /* 64 TLB entries max */ - mtctr r1 - li r4,0 /* TLB # */ - - addi r5,r5,-4 -1: -#ifdef CONFIG_SYS_RAMBOOT - tlbre r3,r4,0 /* Read contents from TLB word #0 */ - rlwinm. r3,r3,0,0x00000200 /* Mask V (valid) bit */ - bne tlbnx2 /* Skip V=1 TLB, this is the SDRAM TLB */ -#endif - lwzu r0,4(r5) - cmpwi r0,0 - beq 2f /* 0 marks end */ - lwzu r1,4(r5) - lwzu r2,4(r5) - tlbwe r0,r4,0 /* TLB Word 0 */ - tlbwe r1,r4,1 /* TLB Word 1 */ - tlbwe r2,r4,2 /* TLB Word 2 */ -tlbnx2: addi r4,r4,1 /* Next TLB */ - bdnz 1b - - /*----------------------------------------------------------------*/ - /* Continue from 'normal' start */ - /*----------------------------------------------------------------*/ -2: - bl 3f - b _start - -3: li r0,0 - mtspr SPRN_SRR1,r0 /* Keep things disabled for now */ - mflr r1 - mtspr SPRN_SRR0,r1 - rfi -#endif /* CONFIG_440 */ - -/* - * r3 - 1st arg to board_init(): IMMP pointer - * r4 - 2nd arg to board_init(): boot flag - */ -#ifndef CONFIG_NAND_SPL - .text - .long 0x27051956 /* U-Boot Magic Number */ - .globl version_string -version_string: - .ascii U_BOOT_VERSION - .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")" - .ascii CONFIG_IDENT_STRING, "\0" - - . = EXC_OFF_SYS_RESET - .globl _start_of_vectors -_start_of_vectors: - -/* Critical input. */ - CRIT_EXCEPTION(0x100, CritcalInput, UnknownException) - -#ifdef CONFIG_440 -/* Machine check */ - MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException) -#else - CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException) -#endif /* CONFIG_440 */ - -/* Data Storage exception. */ - STD_EXCEPTION(0x300, DataStorage, UnknownException) - -/* Instruction Storage exception. */ - STD_EXCEPTION(0x400, InstStorage, UnknownException) - -/* External Interrupt exception. */ - STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) - -/* Alignment exception. */ - . = 0x600 -Alignment: - EXCEPTION_PROLOG(SRR0, SRR1) - mfspr r4,DAR - stw r4,_DAR(r21) - mfspr r5,DSISR - stw r5,_DSISR(r21) - addi r3,r1,STACK_FRAME_OVERHEAD - EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE) - -/* Program check exception */ - . = 0x700 -ProgramCheck: - EXCEPTION_PROLOG(SRR0, SRR1) - addi r3,r1,STACK_FRAME_OVERHEAD - EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException, - MSR_KERNEL, COPY_EE) - -#ifdef CONFIG_440 - STD_EXCEPTION(0x800, FPUnavailable, UnknownException) - STD_EXCEPTION(0x900, Decrementer, DecrementerPITException) - STD_EXCEPTION(0xa00, APU, UnknownException) -#endif - STD_EXCEPTION(0xc00, SystemCall, UnknownException) - -#ifdef CONFIG_440 - STD_EXCEPTION(0x1300, DataTLBError, UnknownException) - STD_EXCEPTION(0x1400, InstructionTLBError, UnknownException) -#else - STD_EXCEPTION(0x1000, PIT, DecrementerPITException) - STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) - STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) -#endif - CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException ) - - .globl _end_of_vectors -_end_of_vectors: - . = _START_OFFSET -#endif - .globl _start -_start: - -/*****************************************************************************/ -#if defined(CONFIG_440) - - /*----------------------------------------------------------------*/ - /* Clear and set up some registers. */ - /*----------------------------------------------------------------*/ - li r0,0x0000 - lis r1,0xffff - mtspr SPRN_DEC,r0 /* prevent dec exceptions */ - mtspr SPRN_TBWL,r0 /* prevent fit & wdt exceptions */ - mtspr SPRN_TBWU,r0 - mtspr SPRN_TSR,r1 /* clear all timer exception status */ - mtspr SPRN_TCR,r0 /* disable all */ - mtspr SPRN_ESR,r0 /* clear exception syndrome register */ - mtxer r0 /* clear integer exception register */ - - /*----------------------------------------------------------------*/ - /* Debug setup -- some (not very good) ice's need an event*/ - /* to establish control :-( Define CONFIG_SYS_INIT_DBCR to the dbsr */ - /* value you need in this case 0x8cff 0000 should do the trick */ - /*----------------------------------------------------------------*/ -#if defined(CONFIG_SYS_INIT_DBCR) - lis r1,0xffff - ori r1,r1,0xffff - mtspr SPRN_DBSR,r1 /* Clear all status bits */ - lis r0,CONFIG_SYS_INIT_DBCR@h - ori r0,r0,CONFIG_SYS_INIT_DBCR@l - mtspr SPRN_DBCR0,r0 - isync -#endif - - /*----------------------------------------------------------------*/ - /* Setup the internal SRAM */ - /*----------------------------------------------------------------*/ - li r0,0 - -#ifdef CONFIG_SYS_INIT_RAM_DCACHE - /* Clear Dcache to use as RAM */ - addis r3,r0,CONFIG_SYS_INIT_RAM_ADDR@h - ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l - addis r4,r0,CONFIG_SYS_INIT_RAM_SIZE@h - ori r4,r4,CONFIG_SYS_INIT_RAM_SIZE@l - rlwinm. r5,r4,0,27,31 - rlwinm r5,r4,27,5,31 - beq ..d_ran - addi r5,r5,0x0001 -..d_ran: - mtctr r5 -..d_ag: - dcbz r0,r3 - addi r3,r3,32 - bdnz ..d_ag - - /* - * Lock the init-ram/stack in d-cache, so that other regions - * may use d-cache as well - * Note, that this current implementation locks exactly 4k - * of d-cache, so please make sure that you don't define a - * bigger init-ram area. Take a look at the lwmon5 440EPx - * implementation as a reference. - */ - msync - isync - /* 8. set TFLOOR/NFLOOR to 8 (-> 8*16*32 bytes locked -> 4k) */ - lis r1,0x0201 - ori r1,r1,0xf808 - mtspr SPRN_DVLIM,r1 - lis r1,0x0808 - ori r1,r1,0x0808 - mtspr SPRN_DNV0,r1 - mtspr SPRN_DNV1,r1 - mtspr SPRN_DNV2,r1 - mtspr SPRN_DNV3,r1 - mtspr SPRN_DTV0,r1 - mtspr SPRN_DTV1,r1 - mtspr SPRN_DTV2,r1 - mtspr SPRN_DTV3,r1 - msync - isync -#endif /* CONFIG_SYS_INIT_RAM_DCACHE */ - - /* 440EP & 440GR are only 440er PPC's without internal SRAM */ -#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) - /* not all PPC's have internal SRAM usable as L2-cache */ -#if defined(CONFIG_440GX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_460SX) - mtdcr L2_CACHE_CFG,r0 /* Ensure L2 Cache is off */ -#elif defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ - defined(CONFIG_APM821XX) - lis r1, 0x0000 - ori r1,r1,0x0008 /* Set L2_CACHE_CFG[RDBW]=1 */ - mtdcr L2_CACHE_CFG,r1 -#endif - - lis r2,0x7fff - ori r2,r2,0xffff - mfdcr r1,ISRAM0_DPC - and r1,r1,r2 /* Disable parity check */ - mtdcr ISRAM0_DPC,r1 - mfdcr r1,ISRAM0_PMEG - and r1,r1,r2 /* Disable pwr mgmt */ - mtdcr ISRAM0_PMEG,r1 - - lis r1,0x8000 /* BAS = 8000_0000 */ -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) - ori r1,r1,0x0980 /* first 64k */ - mtdcr ISRAM0_SB0CR,r1 - lis r1,0x8001 - ori r1,r1,0x0980 /* second 64k */ - mtdcr ISRAM0_SB1CR,r1 - lis r1, 0x8002 - ori r1,r1, 0x0980 /* third 64k */ - mtdcr ISRAM0_SB2CR,r1 - lis r1, 0x8003 - ori r1,r1, 0x0980 /* fourth 64k */ - mtdcr ISRAM0_SB3CR,r1 -#elif defined(CONFIG_440SPE) || defined(CONFIG_460EX) || \ - defined(CONFIG_460GT) || defined(CONFIG_APM821XX) - lis r1,0x0000 /* BAS = X_0000_0000 */ - ori r1,r1,0x0984 /* first 64k */ - mtdcr ISRAM0_SB0CR,r1 - lis r1,0x0001 - ori r1,r1,0x0984 /* second 64k */ - mtdcr ISRAM0_SB1CR,r1 - lis r1, 0x0002 - ori r1,r1, 0x0984 /* third 64k */ - mtdcr ISRAM0_SB2CR,r1 - lis r1, 0x0003 - ori r1,r1, 0x0984 /* fourth 64k */ - mtdcr ISRAM0_SB3CR,r1 -#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ - defined(CONFIG_APM821XX) - lis r2,0x7fff - ori r2,r2,0xffff - mfdcr r1,ISRAM1_DPC - and r1,r1,r2 /* Disable parity check */ - mtdcr ISRAM1_DPC,r1 - mfdcr r1,ISRAM1_PMEG - and r1,r1,r2 /* Disable pwr mgmt */ - mtdcr ISRAM1_PMEG,r1 - - lis r1,0x0004 /* BAS = 4_0004_0000 */ - ori r1,r1,ISRAM1_SIZE /* ocm size */ - mtdcr ISRAM1_SB0CR,r1 -#endif -#elif defined(CONFIG_460SX) - lis r1,0x0000 /* BAS = 0000_0000 */ - ori r1,r1,0x0B84 /* first 128k */ - mtdcr ISRAM0_SB0CR,r1 - lis r1,0x0001 - ori r1,r1,0x0B84 /* second 128k */ - mtdcr ISRAM0_SB1CR,r1 - lis r1, 0x0002 - ori r1,r1, 0x0B84 /* third 128k */ - mtdcr ISRAM0_SB2CR,r1 - lis r1, 0x0003 - ori r1,r1, 0x0B84 /* fourth 128k */ - mtdcr ISRAM0_SB3CR,r1 -#elif defined(CONFIG_440GP) - ori r1,r1,0x0380 /* 8k rw */ - mtdcr ISRAM0_SB0CR,r1 - mtdcr ISRAM0_SB1CR,r0 /* Disable bank 1 */ -#endif -#endif /* #if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) */ - - /*----------------------------------------------------------------*/ - /* Setup the stack in internal SRAM */ - /*----------------------------------------------------------------*/ - lis r1,CONFIG_SYS_INIT_RAM_ADDR@h - ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l - li r0,0 - stwu r0,-4(r1) - stwu r0,-4(r1) /* Terminate call chain */ - - stwu r1,-8(r1) /* Save back chain and move SP */ - lis r0,RESET_VECTOR@h /* Address of reset vector */ - ori r0,r0, RESET_VECTOR@l - stwu r1,-8(r1) /* Save back chain and move SP */ - stw r0,+12(r1) /* Save return addr (underflow vect) */ - -#ifdef CONFIG_NAND_SPL - bl nand_boot_common /* will not return */ -#else - GET_GOT - - bl cpu_init_f /* run low-level CPU init code (from Flash) */ - bl board_init_f - /* NOTREACHED - board_init_f() does not return */ -#endif - -#endif /* CONFIG_440 */ - -/*****************************************************************************/ -#ifdef CONFIG_IOP480 - /*----------------------------------------------------------------------- */ - /* Set up some machine state registers. */ - /*----------------------------------------------------------------------- */ - addi r0,r0,0x0000 /* initialize r0 to zero */ - mtspr SPRN_ESR,r0 /* clear Exception Syndrome Reg */ - mttcr r0 /* timer control register */ - mtexier r0 /* disable all interrupts */ - addis r4,r0,0xFFFF /* set r4 to 0xFFFFFFFF (status in the */ - ori r4,r4,0xFFFF /* dbsr is cleared by setting bits to 1) */ - mtdbsr r4 /* clear/reset the dbsr */ - mtexisr r4 /* clear all pending interrupts */ - addis r4,r0,0x8000 - mtexier r4 /* enable critical exceptions */ - addis r4,r0,0x0000 /* assume 403GCX - enable core clk */ - ori r4,r4,0x4020 /* dbling (no harm done on GA and GC */ - mtiocr r4 /* since bit not used) & DRC to latch */ - /* data bus on rising edge of CAS */ - /*----------------------------------------------------------------------- */ - /* Clear XER. */ - /*----------------------------------------------------------------------- */ - mtxer r0 - /*----------------------------------------------------------------------- */ - /* Invalidate i-cache and d-cache TAG arrays. */ - /*----------------------------------------------------------------------- */ - addi r3,0,1024 /* 1/4 of I-cache size, half of D-cache */ - addi r4,0,1024 /* 1/4 of I-cache */ -..cloop: - iccci 0,r3 - iccci r4,r3 - dccci 0,r3 - addic. r3,r3,-16 /* move back one cache line */ - bne ..cloop /* loop back to do rest until r3 = 0 */ - - /* */ - /* initialize IOP480 so it can read 1 MB code area for SRAM spaces */ - /* this requires enabling MA[17..0], by default only MA[12..0] are enabled. */ - /* */ - - /* first copy IOP480 register base address into r3 */ - addis r3,0,0x5000 /* IOP480 register base address hi */ -/* ori r3,r3,0x0000 / IOP480 register base address lo */ - -#ifdef CONFIG_ADCIOP - /* use r4 as the working variable */ - /* turn on CS3 (LOCCTL.7) */ - lwz r4,0x84(r3) /* LOCTL is at offset 0x84 */ - andi. r4,r4,0xff7f /* make bit 7 = 0 -- CS3 mode */ - stw r4,0x84(r3) /* LOCTL is at offset 0x84 */ -#endif - -#ifdef CONFIG_DASA_SIM - /* use r4 as the working variable */ - /* turn on MA17 (LOCCTL.7) */ - lwz r4,0x84(r3) /* LOCTL is at offset 0x84 */ - ori r4,r4,0x80 /* make bit 7 = 1 -- MA17 mode */ - stw r4,0x84(r3) /* LOCTL is at offset 0x84 */ -#endif - - /* turn on MA16..13 (LCS0BRD.12 = 0) */ - lwz r4,0x100(r3) /* LCS0BRD is at offset 0x100 */ - andi. r4,r4,0xefff /* make bit 12 = 0 */ - stw r4,0x100(r3) /* LCS0BRD is at offset 0x100 */ - - /* make sure above stores all comlete before going on */ - sync - - /* last thing, set local init status done bit (DEVINIT.31) */ - lwz r4,0x80(r3) /* DEVINIT is at offset 0x80 */ - oris r4,r4,0x8000 /* make bit 31 = 1 */ - stw r4,0x80(r3) /* DEVINIT is at offset 0x80 */ - - /* clear all pending interrupts and disable all interrupts */ - li r4,-1 /* set p1 to 0xffffffff */ - stw r4,0x1b0(r3) /* clear all pending interrupts */ - stw r4,0x1b8(r3) /* clear all pending interrupts */ - li r4,0 /* set r4 to 0 */ - stw r4,0x1b4(r3) /* disable all interrupts */ - stw r4,0x1bc(r3) /* disable all interrupts */ - - /* make sure above stores all comlete before going on */ - sync - - /* Set-up icache cacheability. */ - lis r1, CONFIG_SYS_ICACHE_SACR_VALUE@h - ori r1, r1, CONFIG_SYS_ICACHE_SACR_VALUE@l - mticcr r1 - isync - - /* Set-up dcache cacheability. */ - lis r1, CONFIG_SYS_DCACHE_SACR_VALUE@h - ori r1, r1, CONFIG_SYS_DCACHE_SACR_VALUE@l - mtdccr r1 - - addis r1,r0,CONFIG_SYS_INIT_RAM_ADDR@h - ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET /* set up the stack to SDRAM */ - li r0, 0 /* Make room for stack frame header and */ - stwu r0, -4(r1) /* clear final stack frame so that */ - stwu r0, -4(r1) /* stack backtraces terminate cleanly */ - - GET_GOT /* initialize GOT access */ - - bl board_init_f /* run first part of init code (from Flash) */ - /* NOTREACHED - board_init_f() does not return */ - -#endif /* CONFIG_IOP480 */ - -/*****************************************************************************/ -#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ - defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_405EX) || defined(CONFIG_405) - /*----------------------------------------------------------------------- */ - /* Clear and set up some registers. */ - /*----------------------------------------------------------------------- */ - addi r4,r0,0x0000 -#if !defined(CONFIG_405EX) - mtspr SPRN_SGR,r4 -#else - /* - * On 405EX, completely clearing the SGR leads to PPC hangup - * upon PCIe configuration access. The PCIe memory regions - * need to be guarded! - */ - lis r3,0x0000 - ori r3,r3,0x7FFC - mtspr SPRN_SGR,r3 -#endif - mtspr SPRN_DCWR,r4 - mtesr r4 /* clear Exception Syndrome Reg */ - mttcr r4 /* clear Timer Control Reg */ - mtxer r4 /* clear Fixed-Point Exception Reg */ - mtevpr r4 /* clear Exception Vector Prefix Reg */ - addi r4,r0,(0xFFFF-0x10000) /* set r4 to 0xFFFFFFFF (status in the */ - /* dbsr is cleared by setting bits to 1) */ - mtdbsr r4 /* clear/reset the dbsr */ - - /* Invalidate the i- and d-caches. */ - bl invalidate_icache - bl invalidate_dcache - - /* Set-up icache cacheability. */ - lis r4, CONFIG_SYS_ICACHE_SACR_VALUE@h - ori r4, r4, CONFIG_SYS_ICACHE_SACR_VALUE@l - mticcr r4 - isync - - /* Set-up dcache cacheability. */ - lis r4, CONFIG_SYS_DCACHE_SACR_VALUE@h - ori r4, r4, CONFIG_SYS_DCACHE_SACR_VALUE@l - mtdccr r4 - -#if !(defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))\ - && !defined (CONFIG_XILINX_405) - /*----------------------------------------------------------------------- */ - /* Tune the speed and size for flash CS0 */ - /*----------------------------------------------------------------------- */ - bl ext_bus_cntlr_init -#endif - -#if !(defined(CONFIG_SYS_INIT_DCACHE_CS) || defined(CONFIG_SYS_TEMP_STACK_OCM)) - /* - * For boards that don't have OCM and can't use the data cache - * for their primordial stack, setup stack here directly after the - * SDRAM is initialized in ext_bus_cntlr_init. - */ - lis r1, CONFIG_SYS_INIT_RAM_ADDR@h - ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in SDRAM */ - - li r0, 0 /* Make room for stack frame header and */ - stwu r0, -4(r1) /* clear final stack frame so that */ - stwu r0, -4(r1) /* stack backtraces terminate cleanly */ - /* - * Set up a dummy frame to store reset vector as return address. - * this causes stack underflow to reset board. - */ - stwu r1, -8(r1) /* Save back chain and move SP */ - lis r0, RESET_VECTOR@h /* Address of reset vector */ - ori r0, r0, RESET_VECTOR@l - stwu r1, -8(r1) /* Save back chain and move SP */ - stw r0, +12(r1) /* Save return addr (underflow vect) */ -#endif /* !(CONFIG_SYS_INIT_DCACHE_CS || !CONFIG_SYS_TEM_STACK_OCM) */ - -#if defined(CONFIG_405EP) - /*----------------------------------------------------------------------- */ - /* DMA Status, clear to come up clean */ - /*----------------------------------------------------------------------- */ - addis r3,r0, 0xFFFF /* Clear all existing DMA status */ - ori r3,r3, 0xFFFF - mtdcr DMASR, r3 - - bl ppc405ep_init /* do ppc405ep specific init */ -#endif /* CONFIG_405EP */ - -#if defined(CONFIG_SYS_OCM_DATA_ADDR) && defined(CONFIG_SYS_OCM_DATA_SIZE) -#if defined(CONFIG_405EZ) - /******************************************************************** - * Setup OCM - On Chip Memory - PPC405EZ uses OCM Controller V2 - *******************************************************************/ - /* - * We can map the OCM on the PLB3, so map it at - * CONFIG_SYS_OCM_DATA_ADDR + 0x8000 - */ - lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */ - ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l - ori r3,r3,0x0270 /* 16K for Bank 1, R/W/Enable */ - mtdcr OCM0_PLBCR1,r3 /* Set PLB Access */ - ori r3,r3,0x4000 /* Add 0x4000 for bank 2 */ - mtdcr OCM0_PLBCR2,r3 /* Set PLB Access */ - isync - - lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */ - ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l - ori r3,r3,0x0270 /* 16K for Bank 1, R/W/Enable */ - mtdcr OCM0_DSRC1, r3 /* Set Data Side */ - mtdcr OCM0_ISRC1, r3 /* Set Instruction Side */ - ori r3,r3,0x4000 /* Add 0x4000 for bank 2 */ - mtdcr OCM0_DSRC2, r3 /* Set Data Side */ - mtdcr OCM0_ISRC2, r3 /* Set Instruction Side */ - addis r3,0,0x0800 /* OCM Data Parity Disable - 1 Wait State */ - mtdcr OCM0_DISDPC,r3 - - isync -#else /* CONFIG_405EZ */ - /******************************************************************** - * Setup OCM - On Chip Memory - *******************************************************************/ - /* Setup OCM */ - lis r0, 0x7FFF - ori r0, r0, 0xFFFF - mfdcr r3, OCM0_ISCNTL /* get instr-side IRAM config */ - mfdcr r4, OCM0_DSCNTL /* get data-side IRAM config */ - and r3, r3, r0 /* disable data-side IRAM */ - and r4, r4, r0 /* disable data-side IRAM */ - mtdcr OCM0_ISCNTL, r3 /* set instr-side IRAM config */ - mtdcr OCM0_DSCNTL, r4 /* set data-side IRAM config */ - isync - - lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */ - ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l - mtdcr OCM0_DSARC, r3 - addis r4, 0, 0xC000 /* OCM data area enabled */ - mtdcr OCM0_DSCNTL, r4 - isync -#endif /* CONFIG_405EZ */ -#endif - - /*----------------------------------------------------------------------- */ - /* Setup temporary stack in DCACHE or OCM if needed for SDRAM SPD. */ - /*----------------------------------------------------------------------- */ -#ifdef CONFIG_SYS_INIT_DCACHE_CS - li r4, PBxAP - mtdcr EBC0_CFGADDR, r4 - lis r4, CONFIG_SYS_INIT_DCACHE_PBxAR@h - ori r4, r4, CONFIG_SYS_INIT_DCACHE_PBxAR@l - mtdcr EBC0_CFGDATA, r4 - - addi r4, 0, PBxCR - mtdcr EBC0_CFGADDR, r4 - lis r4, CONFIG_SYS_INIT_DCACHE_PBxCR@h - ori r4, r4, CONFIG_SYS_INIT_DCACHE_PBxCR@l - mtdcr EBC0_CFGDATA, r4 - - /* - * Enable the data cache for the 128MB storage access control region - * at CONFIG_SYS_INIT_RAM_ADDR. - */ - mfdccr r4 - oris r4, r4, PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@h - ori r4, r4, PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@l - mtdccr r4 - - /* - * Preallocate data cache lines to be used to avoid a subsequent - * cache miss and an ensuing machine check exception when exceptions - * are enabled. - */ - li r0, 0 - - lis r3, CONFIG_SYS_INIT_RAM_ADDR@h - ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l - - lis r4, CONFIG_SYS_INIT_RAM_SIZE@h - ori r4, r4, CONFIG_SYS_INIT_RAM_SIZE@l - - /* - * Convert the size, in bytes, to the number of cache lines/blocks - * to preallocate. - */ - clrlwi. r5, r4, (32 - L1_CACHE_SHIFT) - srwi r5, r4, L1_CACHE_SHIFT - beq ..load_counter - addi r5, r5, 0x0001 -..load_counter: - mtctr r5 - - /* Preallocate the computed number of cache blocks. */ -..alloc_dcache_block: - dcba r0, r3 - addi r3, r3, L1_CACHE_BYTES - bdnz ..alloc_dcache_block - sync - - /* - * Load the initial stack pointer and data area and convert the size, - * in bytes, to the number of words to initialize to a known value. - */ - lis r1, CONFIG_SYS_INIT_RAM_ADDR@h - ori r1, r1, CONFIG_SYS_INIT_SP_OFFSET@l - - lis r4, (CONFIG_SYS_INIT_RAM_SIZE >> 2)@h - ori r4, r4, (CONFIG_SYS_INIT_RAM_SIZE >> 2)@l - mtctr r4 - - lis r2, CONFIG_SYS_INIT_RAM_ADDR@h - ori r2, r2, CONFIG_SYS_INIT_RAM_SIZE@l - - lis r4, CONFIG_SYS_INIT_RAM_PATTERN@h - ori r4, r4, CONFIG_SYS_INIT_RAM_PATTERN@l - -..stackloop: - stwu r4, -4(r2) - bdnz ..stackloop - - /* - * Make room for stack frame header and clear final stack frame so - * that stack backtraces terminate cleanly. - */ - stwu r0, -4(r1) - stwu r0, -4(r1) - - /* - * Set up a dummy frame to store reset vector as return address. - * this causes stack underflow to reset board. - */ - stwu r1, -8(r1) /* Save back chain and move SP */ - addis r0, 0, RESET_VECTOR@h /* Address of reset vector */ - ori r0, r0, RESET_VECTOR@l - stwu r1, -8(r1) /* Save back chain and move SP */ - stw r0, +12(r1) /* Save return addr (underflow vect) */ - -#elif defined(CONFIG_SYS_TEMP_STACK_OCM) && \ - (defined(CONFIG_SYS_OCM_DATA_ADDR) && defined(CONFIG_SYS_OCM_DATA_SIZE)) - /* - * Stack in OCM. - */ - - /* Set up Stack at top of OCM */ - lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@h - ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@l - - /* Set up a zeroized stack frame so that backtrace works right */ - li r0, 0 - stwu r0, -4(r1) - stwu r0, -4(r1) - - /* - * Set up a dummy frame to store reset vector as return address. - * this causes stack underflow to reset board. - */ - stwu r1, -8(r1) /* Save back chain and move SP */ - lis r0, RESET_VECTOR@h /* Address of reset vector */ - ori r0, r0, RESET_VECTOR@l - stwu r1, -8(r1) /* Save back chain and move SP */ - stw r0, +12(r1) /* Save return addr (underflow vect) */ -#endif /* CONFIG_SYS_INIT_DCACHE_CS */ - -#ifdef CONFIG_NAND_SPL - bl nand_boot_common /* will not return */ -#else - GET_GOT /* initialize GOT access */ - - bl cpu_init_f /* run low-level CPU init code (from Flash) */ - - bl board_init_f /* run first part of init code (from Flash) */ - /* NOTREACHED - board_init_f() does not return */ - -#endif /* CONFIG_NAND_SPL */ - -#endif /* CONFIG_405GP || CONFIG_405CR || CONFIG_405 || CONFIG_405EP */ - /*----------------------------------------------------------------------- */ - - -#ifndef CONFIG_NAND_SPL -/* - * This code finishes saving the registers to the exception frame - * and jumps to the appropriate handler for the exception. - * Register r21 is pointer into trap frame, r1 has new stack pointer. - */ - .globl transfer_to_handler -transfer_to_handler: - stw r22,_NIP(r21) - lis r22,MSR_POW@h - andc r23,r23,r22 - stw r23,_MSR(r21) - SAVE_GPR(7, r21) - SAVE_4GPRS(8, r21) - SAVE_8GPRS(12, r21) - SAVE_8GPRS(24, r21) - mflr r23 - andi. r24,r23,0x3f00 /* get vector offset */ - stw r24,TRAP(r21) - li r22,0 - stw r22,RESULT(r21) - mtspr SPRG2,r22 /* r1 is now kernel sp */ - lwz r24,0(r23) /* virtual address of handler */ - lwz r23,4(r23) /* where to go when done */ - mtspr SRR0,r24 - mtspr SRR1,r20 - mtlr r23 - SYNC - rfi /* jump to handler, enable MMU */ - -int_return: - mfmsr r28 /* Disable interrupts */ - li r4,0 - ori r4,r4,MSR_EE - andc r28,r28,r4 - SYNC /* Some chip revs need this... */ - mtmsr r28 - SYNC - lwz r2,_CTR(r1) - lwz r0,_LINK(r1) - mtctr r2 - mtlr r0 - lwz r2,_XER(r1) - lwz r0,_CCR(r1) - mtspr XER,r2 - mtcrf 0xFF,r0 - REST_10GPRS(3, r1) - REST_10GPRS(13, r1) - REST_8GPRS(23, r1) - REST_GPR(31, r1) - lwz r2,_NIP(r1) /* Restore environment */ - lwz r0,_MSR(r1) - mtspr SRR0,r2 - mtspr SRR1,r0 - lwz r0,GPR0(r1) - lwz r2,GPR2(r1) - lwz r1,GPR1(r1) - SYNC - rfi - -crit_return: - mfmsr r28 /* Disable interrupts */ - li r4,0 - ori r4,r4,MSR_EE - andc r28,r28,r4 - SYNC /* Some chip revs need this... */ - mtmsr r28 - SYNC - lwz r2,_CTR(r1) - lwz r0,_LINK(r1) - mtctr r2 - mtlr r0 - lwz r2,_XER(r1) - lwz r0,_CCR(r1) - mtspr XER,r2 - mtcrf 0xFF,r0 - REST_10GPRS(3, r1) - REST_10GPRS(13, r1) - REST_8GPRS(23, r1) - REST_GPR(31, r1) - lwz r2,_NIP(r1) /* Restore environment */ - lwz r0,_MSR(r1) - mtspr SPRN_CSRR0,r2 - mtspr SPRN_CSRR1,r0 - lwz r0,GPR0(r1) - lwz r2,GPR2(r1) - lwz r1,GPR1(r1) - SYNC - rfci - -#ifdef CONFIG_440 -mck_return: - mfmsr r28 /* Disable interrupts */ - li r4,0 - ori r4,r4,MSR_EE - andc r28,r28,r4 - SYNC /* Some chip revs need this... */ - mtmsr r28 - SYNC - lwz r2,_CTR(r1) - lwz r0,_LINK(r1) - mtctr r2 - mtlr r0 - lwz r2,_XER(r1) - lwz r0,_CCR(r1) - mtspr XER,r2 - mtcrf 0xFF,r0 - REST_10GPRS(3, r1) - REST_10GPRS(13, r1) - REST_8GPRS(23, r1) - REST_GPR(31, r1) - lwz r2,_NIP(r1) /* Restore environment */ - lwz r0,_MSR(r1) - mtspr SPRN_MCSRR0,r2 - mtspr SPRN_MCSRR1,r0 - lwz r0,GPR0(r1) - lwz r2,GPR2(r1) - lwz r1,GPR1(r1) - SYNC - rfmci -#endif /* CONFIG_440 */ - - - .globl get_pvr -get_pvr: - mfspr r3, PVR - blr - -/*------------------------------------------------------------------------------- */ -/* Function: out16 */ -/* Description: Output 16 bits */ -/*------------------------------------------------------------------------------- */ - .globl out16 -out16: - sth r4,0x0000(r3) - blr - -/*------------------------------------------------------------------------------- */ -/* Function: out16r */ -/* Description: Byte reverse and output 16 bits */ -/*------------------------------------------------------------------------------- */ - .globl out16r -out16r: - sthbrx r4,r0,r3 - blr - -/*------------------------------------------------------------------------------- */ -/* Function: out32r */ -/* Description: Byte reverse and output 32 bits */ -/*------------------------------------------------------------------------------- */ - .globl out32r -out32r: - stwbrx r4,r0,r3 - blr - -/*------------------------------------------------------------------------------- */ -/* Function: in16 */ -/* Description: Input 16 bits */ -/*------------------------------------------------------------------------------- */ - .globl in16 -in16: - lhz r3,0x0000(r3) - blr - -/*------------------------------------------------------------------------------- */ -/* Function: in16r */ -/* Description: Input 16 bits and byte reverse */ -/*------------------------------------------------------------------------------- */ - .globl in16r -in16r: - lhbrx r3,r0,r3 - blr - -/*------------------------------------------------------------------------------- */ -/* Function: in32r */ -/* Description: Input 32 bits and byte reverse */ -/*------------------------------------------------------------------------------- */ - .globl in32r -in32r: - lwbrx r3,r0,r3 - blr - -/* - * void relocate_code (addr_sp, gd, addr_moni) - * - * This "function" does not return, instead it continues in RAM - * after relocating the monitor code. - * - * r3 = Relocated stack pointer - * r4 = Relocated global data pointer - * r5 = Relocated text pointer - */ - .globl relocate_code -relocate_code: -#if defined(CONFIG_4xx_DCACHE) || defined(CONFIG_SYS_INIT_DCACHE_CS) - /* - * We need to flush the initial global data (gd_t) and bd_info - * before the dcache will be invalidated. - */ - - /* Save registers */ - mr r9, r3 - mr r10, r4 - mr r11, r5 - - /* - * Flush complete dcache, this is faster than flushing the - * ranges for global_data and bd_info instead. - */ - bl flush_dcache - -#if defined(CONFIG_SYS_INIT_DCACHE_CS) - /* - * Undo the earlier data cache set-up for the primordial stack and - * data area. First, invalidate the data cache and then disable data - * cacheability for that area. Finally, restore the EBC values, if - * any. - */ - - /* Invalidate the primordial stack and data area in cache */ - lis r3, CONFIG_SYS_INIT_RAM_ADDR@h - ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l - - lis r4, CONFIG_SYS_INIT_RAM_SIZE@h - ori r4, r4, CONFIG_SYS_INIT_RAM_SIZE@l - add r4, r4, r3 - - bl invalidate_dcache_range - - /* Disable cacheability for the region */ - mfdccr r3 - lis r4, ~PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@h - ori r4, r4, ~PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@l - and r3, r3, r4 - mtdccr r3 - - /* Restore the EBC parameters */ - li r3, PBxAP - mtdcr EBC0_CFGADDR, r3 - lis r3, PBxAP_VAL@h - ori r3, r3, PBxAP_VAL@l - mtdcr EBC0_CFGDATA, r3 - - li r3, PBxCR - mtdcr EBC0_CFGADDR, r3 - lis r3, PBxCR_VAL@h - ori r3, r3, PBxCR_VAL@l - mtdcr EBC0_CFGDATA, r3 -#endif /* defined(CONFIG_SYS_INIT_DCACHE_CS) */ - - /* Restore registers */ - mr r3, r9 - mr r4, r10 - mr r5, r11 -#endif /* defined(CONFIG_4xx_DCACHE) || defined(CONFIG_SYS_INIT_DCACHE_CS) */ - -#ifdef CONFIG_SYS_INIT_RAM_DCACHE - /* - * Unlock the previously locked d-cache - */ - msync - isync - /* set TFLOOR/NFLOOR to 0 again */ - lis r6,0x0001 - ori r6,r6,0xf800 - mtspr SPRN_DVLIM,r6 - lis r6,0x0000 - ori r6,r6,0x0000 - mtspr SPRN_DNV0,r6 - mtspr SPRN_DNV1,r6 - mtspr SPRN_DNV2,r6 - mtspr SPRN_DNV3,r6 - mtspr SPRN_DTV0,r6 - mtspr SPRN_DTV1,r6 - mtspr SPRN_DTV2,r6 - mtspr SPRN_DTV3,r6 - msync - isync - - /* Invalidate data cache, now no longer our stack */ - dccci 0,0 - sync - isync -#endif /* CONFIG_SYS_INIT_RAM_DCACHE */ - - /* - * On some 440er platforms the cache is enabled in the first TLB (Boot-CS) - * to speed up the boot process. Now this cache needs to be disabled. - */ -#if defined(CONFIG_440) - /* Clear all potential pending exceptions */ - mfspr r1,SPRN_MCSR - mtspr SPRN_MCSR,r1 - addi r1,r0,CONFIG_SYS_TLB_FOR_BOOT_FLASH /* Use defined TLB */ - tlbre r0,r1,0x0002 /* Read contents */ - ori r0,r0,0x0c00 /* Or in the inhibit, write through bit */ - tlbwe r0,r1,0x0002 /* Save it out */ - sync - isync -#endif /* defined(CONFIG_440) */ - mr r1, r3 /* Set new stack pointer */ - mr r9, r4 /* Save copy of Init Data pointer */ - mr r10, r5 /* Save copy of Destination Address */ - - GET_GOT - mr r3, r5 /* Destination Address */ - lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */ - ori r4, r4, CONFIG_SYS_MONITOR_BASE@l - lwz r5, GOT(__init_end) - sub r5, r5, r4 - li r6, L1_CACHE_BYTES /* Cache Line Size */ - - /* - * Fix GOT pointer: - * - * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address - * - * Offset: - */ - sub r15, r10, r4 - - /* First our own GOT */ - add r12, r12, r15 - /* then the one used by the C code */ - add r30, r30, r15 - - /* - * Now relocate code - */ - - cmplw cr1,r3,r4 - addi r0,r5,3 - srwi. r0,r0,2 - beq cr1,4f /* In place copy is not necessary */ - beq 7f /* Protect against 0 count */ - mtctr r0 - bge cr1,2f - - la r8,-4(r4) - la r7,-4(r3) -1: lwzu r0,4(r8) - stwu r0,4(r7) - bdnz 1b - b 4f - -2: slwi r0,r0,2 - add r8,r4,r0 - add r7,r3,r0 -3: lwzu r0,-4(r8) - stwu r0,-4(r7) - bdnz 3b - -/* - * Now flush the cache: note that we must start from a cache aligned - * address. Otherwise we might miss one cache line. - */ -4: cmpwi r6,0 - add r5,r3,r5 - beq 7f /* Always flush prefetch queue in any case */ - subi r0,r6,1 - andc r3,r3,r0 - mr r4,r3 -5: dcbst 0,r4 - add r4,r4,r6 - cmplw r4,r5 - blt 5b - sync /* Wait for all dcbst to complete on bus */ - mr r4,r3 -6: icbi 0,r4 - add r4,r4,r6 - cmplw r4,r5 - blt 6b -7: sync /* Wait for all icbi to complete on bus */ - isync - -/* - * We are done. Do not return, instead branch to second part of board - * initialization, now running from RAM. - */ - - addi r0, r10, in_ram - _start + _START_OFFSET - mtlr r0 - blr /* NEVER RETURNS! */ - -in_ram: - - /* - * Relocation Function, r12 point to got2+0x8000 - * - * Adjust got2 pointers, no need to check for 0, this code - * already puts a few entries in the table. - */ - li r0,__got2_entries@sectoff@l - la r3,GOT(_GOT2_TABLE_) - lwz r11,GOT(_GOT2_TABLE_) - mtctr r0 - sub r11,r3,r11 - addi r3,r3,-4 -1: lwzu r0,4(r3) - cmpwi r0,0 - beq- 2f - add r0,r0,r11 - stw r0,0(r3) -2: bdnz 1b - - /* - * Now adjust the fixups and the pointers to the fixups - * in case we need to move ourselves again. - */ - li r0,__fixup_entries@sectoff@l - lwz r3,GOT(_FIXUP_TABLE_) - cmpwi r0,0 - mtctr r0 - addi r3,r3,-4 - beq 4f -3: lwzu r4,4(r3) - lwzux r0,r4,r11 - cmpwi r0,0 - add r0,r0,r11 - stw r4,0(r3) - beq- 5f - stw r0,0(r4) -5: bdnz 3b -4: -clear_bss: - /* - * Now clear BSS segment - */ - lwz r3,GOT(__bss_start) - lwz r4,GOT(_end) - - cmplw 0, r3, r4 - beq 7f - - li r0, 0 - - andi. r5, r4, 3 - beq 6f - sub r4, r4, r5 - mtctr r5 - mr r5, r4 -5: stb r0, 0(r5) - addi r5, r5, 1 - bdnz 5b -6: - stw r0, 0(r3) - addi r3, r3, 4 - cmplw 0, r3, r4 - bne 6b - -7: - mr r3, r9 /* Init Data pointer */ - mr r4, r10 /* Destination Address */ - bl board_init_r - - /* - * Copy exception vector code to low memory - * - * r3: dest_addr - * r7: source address, r8: end address, r9: target address - */ - .globl trap_init -trap_init: - mflr r4 /* save link register */ - GET_GOT - lwz r7, GOT(_start_of_vectors) - lwz r8, GOT(_end_of_vectors) - - li r9, 0x100 /* reset vector always at 0x100 */ - - cmplw 0, r7, r8 - bgelr /* return if r7>=r8 - just in case */ -1: - lwz r0, 0(r7) - stw r0, 0(r9) - addi r7, r7, 4 - addi r9, r9, 4 - cmplw 0, r7, r8 - bne 1b - - /* - * relocate `hdlr' and `int_return' entries - */ - li r7, .L_MachineCheck - _start + _START_OFFSET - li r8, Alignment - _start + _START_OFFSET -2: - bl trap_reloc - addi r7, r7, 0x100 /* next exception vector */ - cmplw 0, r7, r8 - blt 2b - - li r7, .L_Alignment - _start + _START_OFFSET - bl trap_reloc - - li r7, .L_ProgramCheck - _start + _START_OFFSET - bl trap_reloc - -#ifdef CONFIG_440 - li r7, .L_FPUnavailable - _start + _START_OFFSET - bl trap_reloc - - li r7, .L_Decrementer - _start + _START_OFFSET - bl trap_reloc - - li r7, .L_APU - _start + _START_OFFSET - bl trap_reloc - - li r7, .L_InstructionTLBError - _start + _START_OFFSET - bl trap_reloc - - li r7, .L_DataTLBError - _start + _START_OFFSET - bl trap_reloc -#else /* CONFIG_440 */ - li r7, .L_PIT - _start + _START_OFFSET - bl trap_reloc - - li r7, .L_InstructionTLBMiss - _start + _START_OFFSET - bl trap_reloc - - li r7, .L_DataTLBMiss - _start + _START_OFFSET - bl trap_reloc -#endif /* CONFIG_440 */ - - li r7, .L_DebugBreakpoint - _start + _START_OFFSET - bl trap_reloc - -#if !defined(CONFIG_440) - addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ - oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */ - mtmsr r7 /* change MSR */ -#else - bl __440_msr_set - b __440_msr_continue - -__440_msr_set: - addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ - oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */ - mtspr SPRN_SRR1,r7 - mflr r7 - mtspr SPRN_SRR0,r7 - rfi -__440_msr_continue: -#endif - - mtlr r4 /* restore link register */ - blr - -#if defined(CONFIG_440) -/*----------------------------------------------------------------------------+ -| dcbz_area. -+----------------------------------------------------------------------------*/ - function_prolog(dcbz_area) - rlwinm. r5,r4,0,27,31 - rlwinm r5,r4,27,5,31 - beq ..d_ra2 - addi r5,r5,0x0001 -..d_ra2:mtctr r5 -..d_ag2:dcbz r0,r3 - addi r3,r3,32 - bdnz ..d_ag2 - sync - blr - function_epilog(dcbz_area) -#endif /* CONFIG_440 */ -#endif /* CONFIG_NAND_SPL */ - -/*------------------------------------------------------------------------------- */ -/* Function: in8 */ -/* Description: Input 8 bits */ -/*------------------------------------------------------------------------------- */ - .globl in8 -in8: - lbz r3,0x0000(r3) - blr - -/*------------------------------------------------------------------------------- */ -/* Function: out8 */ -/* Description: Output 8 bits */ -/*------------------------------------------------------------------------------- */ - .globl out8 -out8: - stb r4,0x0000(r3) - blr - -/*------------------------------------------------------------------------------- */ -/* Function: out32 */ -/* Description: Output 32 bits */ -/*------------------------------------------------------------------------------- */ - .globl out32 -out32: - stw r4,0x0000(r3) - blr - -/*------------------------------------------------------------------------------- */ -/* Function: in32 */ -/* Description: Input 32 bits */ -/*------------------------------------------------------------------------------- */ - .globl in32 -in32: - lwz 3,0x0000(3) - blr - -/**************************************************************************/ -/* PPC405EP specific stuff */ -/**************************************************************************/ -#ifdef CONFIG_405EP -ppc405ep_init: - -#ifdef CONFIG_BUBINGA - /* - * Initialize EBC chip selects 1 & 4 and GPIO pins (for alternate - * function) to support FPGA and NVRAM accesses below. - */ - - lis r3,GPIO0_OSRH@h /* config GPIO output select */ - ori r3,r3,GPIO0_OSRH@l - lis r4,CONFIG_SYS_GPIO0_OSRH@h - ori r4,r4,CONFIG_SYS_GPIO0_OSRH@l - stw r4,0(r3) - lis r3,GPIO0_OSRL@h - ori r3,r3,GPIO0_OSRL@l - lis r4,CONFIG_SYS_GPIO0_OSRL@h - ori r4,r4,CONFIG_SYS_GPIO0_OSRL@l - stw r4,0(r3) - - lis r3,GPIO0_ISR1H@h /* config GPIO input select */ - ori r3,r3,GPIO0_ISR1H@l - lis r4,CONFIG_SYS_GPIO0_ISR1H@h - ori r4,r4,CONFIG_SYS_GPIO0_ISR1H@l - stw r4,0(r3) - lis r3,GPIO0_ISR1L@h - ori r3,r3,GPIO0_ISR1L@l - lis r4,CONFIG_SYS_GPIO0_ISR1L@h - ori r4,r4,CONFIG_SYS_GPIO0_ISR1L@l - stw r4,0(r3) - - lis r3,GPIO0_TSRH@h /* config GPIO three-state select */ - ori r3,r3,GPIO0_TSRH@l - lis r4,CONFIG_SYS_GPIO0_TSRH@h - ori r4,r4,CONFIG_SYS_GPIO0_TSRH@l - stw r4,0(r3) - lis r3,GPIO0_TSRL@h - ori r3,r3,GPIO0_TSRL@l - lis r4,CONFIG_SYS_GPIO0_TSRL@h - ori r4,r4,CONFIG_SYS_GPIO0_TSRL@l - stw r4,0(r3) - - lis r3,GPIO0_TCR@h /* config GPIO driver output enables */ - ori r3,r3,GPIO0_TCR@l - lis r4,CONFIG_SYS_GPIO0_TCR@h - ori r4,r4,CONFIG_SYS_GPIO0_TCR@l - stw r4,0(r3) - - li r3,PB1AP /* program EBC bank 1 for RTC access */ - mtdcr EBC0_CFGADDR,r3 - lis r3,CONFIG_SYS_EBC_PB1AP@h - ori r3,r3,CONFIG_SYS_EBC_PB1AP@l - mtdcr EBC0_CFGDATA,r3 - li r3,PB1CR - mtdcr EBC0_CFGADDR,r3 - lis r3,CONFIG_SYS_EBC_PB1CR@h - ori r3,r3,CONFIG_SYS_EBC_PB1CR@l - mtdcr EBC0_CFGDATA,r3 - - li r3,PB1AP /* program EBC bank 1 for RTC access */ - mtdcr EBC0_CFGADDR,r3 - lis r3,CONFIG_SYS_EBC_PB1AP@h - ori r3,r3,CONFIG_SYS_EBC_PB1AP@l - mtdcr EBC0_CFGDATA,r3 - li r3,PB1CR - mtdcr EBC0_CFGADDR,r3 - lis r3,CONFIG_SYS_EBC_PB1CR@h - ori r3,r3,CONFIG_SYS_EBC_PB1CR@l - mtdcr EBC0_CFGDATA,r3 - - li r3,PB4AP /* program EBC bank 4 for FPGA access */ - mtdcr EBC0_CFGADDR,r3 - lis r3,CONFIG_SYS_EBC_PB4AP@h - ori r3,r3,CONFIG_SYS_EBC_PB4AP@l - mtdcr EBC0_CFGDATA,r3 - li r3,PB4CR - mtdcr EBC0_CFGADDR,r3 - lis r3,CONFIG_SYS_EBC_PB4CR@h - ori r3,r3,CONFIG_SYS_EBC_PB4CR@l - mtdcr EBC0_CFGDATA,r3 -#endif - - /* - !----------------------------------------------------------------------- - ! Check to see if chip is in bypass mode. - ! If so, write stored CPC0_PLLMR0 and CPC0_PLLMR1 values and perform a - ! CPU reset Otherwise, skip this step and keep going. - ! Note: Running BIOS in bypass mode is not supported since PLB speed - ! will not be fast enough for the SDRAM (min 66MHz) - !----------------------------------------------------------------------- - */ - mfdcr r5, CPC0_PLLMR1 - rlwinm r4,r5,1,0x1 /* get system clock source (SSCS) */ - cmpi cr0,0,r4,0x1 - - beq pll_done /* if SSCS =b'1' then PLL has */ - /* already been set */ - /* and CPU has been reset */ - /* so skip to next section */ - -#ifdef CONFIG_BUBINGA - /* - !----------------------------------------------------------------------- - ! Read NVRAM to get value to write in PLLMR. - ! If value has not been correctly saved, write default value - ! Default config values (assuming on-board 33MHz SYS_CLK) are above. - ! See CPU_DEFAULT_200 and CPU_DEFAULT_266 above. - ! - ! WARNING: This code assumes the first three words in the nvram_t - ! structure in openbios.h. Changing the beginning of - ! the structure will break this code. - ! - !----------------------------------------------------------------------- - */ - addis r3,0,NVRAM_BASE@h - addi r3,r3,NVRAM_BASE@l - - lwz r4, 0(r3) - addis r5,0,NVRVFY1@h - addi r5,r5,NVRVFY1@l - cmp cr0,0,r4,r5 /* Compare 1st NVRAM Magic number*/ - bne ..no_pllset - addi r3,r3,4 - lwz r4, 0(r3) - addis r5,0,NVRVFY2@h - addi r5,r5,NVRVFY2@l - cmp cr0,0,r4,r5 /* Compare 2 NVRAM Magic number */ - bne ..no_pllset - addi r3,r3,8 /* Skip over conf_size */ - lwz r4, 4(r3) /* Load PLLMR1 value from NVRAM */ - lwz r3, 0(r3) /* Load PLLMR0 value from NVRAM */ - rlwinm r5,r4,1,0x1 /* get system clock source (SSCS) */ - cmpi cr0,0,r5,1 /* See if PLL is locked */ - beq pll_write -..no_pllset: -#endif /* CONFIG_BUBINGA */ - -#ifdef CONFIG_TAIHU - mfdcr r4, CPC0_BOOT - andi. r5, r4, CPC0_BOOT_SEP@l - bne strap_1 /* serial eeprom present */ - addis r5,0,CPLD_REG0_ADDR@h - ori r5,r5,CPLD_REG0_ADDR@l - andi. r5, r5, 0x10 - bne _pci_66mhz -#endif /* CONFIG_TAIHU */ - -#if defined(CONFIG_ZEUS) - mfdcr r4, CPC0_BOOT - andi. r5, r4, CPC0_BOOT_SEP@l - bne strap_1 /* serial eeprom present */ - lis r3,0x0000 - addi r3,r3,0x3030 - lis r4,0x8042 - addi r4,r4,0x223e - b 1f -strap_1: - mfdcr r3, CPC0_PLLMR0 - mfdcr r4, CPC0_PLLMR1 - b 1f -#endif - - addis r3,0,PLLMR0_DEFAULT@h /* PLLMR0 default value */ - ori r3,r3,PLLMR0_DEFAULT@l /* */ - addis r4,0,PLLMR1_DEFAULT@h /* PLLMR1 default value */ - ori r4,r4,PLLMR1_DEFAULT@l /* */ - -#ifdef CONFIG_TAIHU - b 1f -_pci_66mhz: - addis r3,0,PLLMR0_DEFAULT_PCI66@h - ori r3,r3,PLLMR0_DEFAULT_PCI66@l - addis r4,0,PLLMR1_DEFAULT_PCI66@h - ori r4,r4,PLLMR1_DEFAULT_PCI66@l - b 1f -strap_1: - mfdcr r3, CPC0_PLLMR0 - mfdcr r4, CPC0_PLLMR1 -#endif /* CONFIG_TAIHU */ - -1: - b pll_write /* Write the CPC0_PLLMR with new value */ - -pll_done: - /* - !----------------------------------------------------------------------- - ! Clear Soft Reset Register - ! This is needed to enable PCI if not booting from serial EPROM - !----------------------------------------------------------------------- - */ - addi r3, 0, 0x0 - mtdcr CPC0_SRR, r3 - - addis r3,0,0x0010 - mtctr r3 -pci_wait: - bdnz pci_wait - - blr /* return to main code */ - -/* -!----------------------------------------------------------------------------- -! Function: pll_write -! Description: Updates the value of the CPC0_PLLMR according to CMOS27E documentation -! That is: -! 1. Pll is first disabled (de-activated by putting in bypass mode) -! 2. PLL is reset -! 3. Clock dividers are set while PLL is held in reset and bypassed -! 4. PLL Reset is cleared -! 5. Wait 100us for PLL to lock -! 6. A core reset is performed -! Input: r3 = Value to write to CPC0_PLLMR0 -! Input: r4 = Value to write to CPC0_PLLMR1 -! Output r3 = none -!----------------------------------------------------------------------------- -*/ - .globl pll_write -pll_write: - mfdcr r5, CPC0_UCR - andis. r5,r5,0xFFFF - ori r5,r5,0x0101 /* Stop the UART clocks */ - mtdcr CPC0_UCR,r5 /* Before changing PLL */ - - mfdcr r5, CPC0_PLLMR1 - rlwinm r5,r5,0,0x7FFFFFFF /* Disable PLL */ - mtdcr CPC0_PLLMR1,r5 - oris r5,r5,0x4000 /* Set PLL Reset */ - mtdcr CPC0_PLLMR1,r5 - - mtdcr CPC0_PLLMR0,r3 /* Set clock dividers */ - rlwinm r5,r4,0,0x3FFFFFFF /* Reset & Bypass new PLL dividers */ - oris r5,r5,0x4000 /* Set PLL Reset */ - mtdcr CPC0_PLLMR1,r5 /* Set clock dividers */ - rlwinm r5,r5,0,0xBFFFFFFF /* Clear PLL Reset */ - mtdcr CPC0_PLLMR1,r5 - - /* - ! Wait min of 100us for PLL to lock. - ! See CMOS 27E databook for more info. - ! At 200MHz, that means waiting 20,000 instructions - */ - addi r3,0,20000 /* 2000 = 0x4e20 */ - mtctr r3 -pll_wait: - bdnz pll_wait - - oris r5,r5,0x8000 /* Enable PLL */ - mtdcr CPC0_PLLMR1,r5 /* Engage */ - - /* - * Reset CPU to guarantee timings are OK - * Not sure if this is needed... - */ - addis r3,0,0x1000 - mtspr SPRN_DBCR0,r3 /* This will cause a CPU core reset, and */ - /* execution will continue from the poweron */ - /* vector of 0xfffffffc */ -#endif /* CONFIG_405EP */ - -#if defined(CONFIG_440) -/*----------------------------------------------------------------------------+ -| mttlb3. -+----------------------------------------------------------------------------*/ - function_prolog(mttlb3) - TLBWE(4,3,2) - blr - function_epilog(mttlb3) - -/*----------------------------------------------------------------------------+ -| mftlb3. -+----------------------------------------------------------------------------*/ - function_prolog(mftlb3) - TLBRE(3,3,2) - blr - function_epilog(mftlb3) - -/*----------------------------------------------------------------------------+ -| mttlb2. -+----------------------------------------------------------------------------*/ - function_prolog(mttlb2) - TLBWE(4,3,1) - blr - function_epilog(mttlb2) - -/*----------------------------------------------------------------------------+ -| mftlb2. -+----------------------------------------------------------------------------*/ - function_prolog(mftlb2) - TLBRE(3,3,1) - blr - function_epilog(mftlb2) - -/*----------------------------------------------------------------------------+ -| mttlb1. -+----------------------------------------------------------------------------*/ - function_prolog(mttlb1) - TLBWE(4,3,0) - blr - function_epilog(mttlb1) - -/*----------------------------------------------------------------------------+ -| mftlb1. -+----------------------------------------------------------------------------*/ - function_prolog(mftlb1) - TLBRE(3,3,0) - blr - function_epilog(mftlb1) -#endif /* CONFIG_440 */ - -#if defined(CONFIG_NAND_SPL) -/* - * void nand_boot_relocate(dst, src, bytes) - * - * r3 = Destination address to copy code to (in SDRAM) - * r4 = Source address to copy code from - * r5 = size to copy in bytes - */ -nand_boot_relocate: - mr r6,r3 - mr r7,r4 - mflr r8 - - /* - * Copy SPL from icache into SDRAM - */ - subi r3,r3,4 - subi r4,r4,4 - srwi r5,r5,2 - mtctr r5 -..spl_loop: - lwzu r0,4(r4) - stwu r0,4(r3) - bdnz ..spl_loop - - /* - * Calculate "corrected" link register, so that we "continue" - * in execution in destination range - */ - sub r3,r7,r6 /* r3 = src - dst */ - sub r8,r8,r3 /* r8 = link-reg - (src - dst) */ - mtlr r8 - blr - -nand_boot_common: - /* - * First initialize SDRAM. It has to be available *before* calling - * nand_boot(). - */ - lis r3,CONFIG_SYS_SDRAM_BASE@h - ori r3,r3,CONFIG_SYS_SDRAM_BASE@l - bl initdram - - /* - * Now copy the 4k SPL code into SDRAM and continue execution - * from there. - */ - lis r3,CONFIG_SYS_NAND_BOOT_SPL_DST@h - ori r3,r3,CONFIG_SYS_NAND_BOOT_SPL_DST@l - lis r4,CONFIG_SYS_NAND_BOOT_SPL_SRC@h - ori r4,r4,CONFIG_SYS_NAND_BOOT_SPL_SRC@l - lis r5,CONFIG_SYS_NAND_BOOT_SPL_SIZE@h - ori r5,r5,CONFIG_SYS_NAND_BOOT_SPL_SIZE@l - bl nand_boot_relocate - - /* - * We're running from SDRAM now!!! - * - * It is necessary for 4xx systems to relocate from running at - * the original location (0xfffffxxx) to somewhere else (SDRAM - * preferably). This is because CS0 needs to be reconfigured for - * NAND access. And we can't reconfigure this CS when currently - * "running" from it. - */ - - /* - * Finally call nand_boot() to load main NAND U-Boot image from - * NAND and jump to it. - */ - bl nand_boot /* will not return */ -#endif /* CONFIG_NAND_SPL */ diff --git a/arch/powerpc/cpu/ppc4xx/tlb.c b/arch/powerpc/cpu/ppc4xx/tlb.c deleted file mode 100644 index 684da92..0000000 --- a/arch/powerpc/cpu/ppc4xx/tlb.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * (C) Copyright 2007 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> - -#if defined(CONFIG_440) - -#include <asm/ppc440.h> -#include <asm/cache.h> -#include <asm/io.h> -#include <asm/mmu.h> - -typedef struct region { - u64 base; - u32 size; - u32 tlb_word2_i_value; -} region_t; - -void remove_tlb(u32 vaddr, u32 size) -{ - int i; - u32 tlb_word0_value; - u32 tlb_vaddr; - u32 tlb_size = 0; - - for (i=0; i<PPC4XX_TLB_SIZE; i++) { - tlb_word0_value = mftlb1(i); - tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value); - if (((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_ENABLE) && - (tlb_vaddr >= vaddr)) { - /* - * TLB is enabled and start address is lower or equal - * than the area we are looking for. Now we only have - * to check the size/end address for a match. - */ - switch (tlb_word0_value & TLB_WORD0_SIZE_MASK) { - case TLB_WORD0_SIZE_1KB: - tlb_size = 1 << 10; - break; - case TLB_WORD0_SIZE_4KB: - tlb_size = 4 << 10; - break; - case TLB_WORD0_SIZE_16KB: - tlb_size = 16 << 10; - break; - case TLB_WORD0_SIZE_64KB: - tlb_size = 64 << 10; - break; - case TLB_WORD0_SIZE_256KB: - tlb_size = 256 << 10; - break; - case TLB_WORD0_SIZE_1MB: - tlb_size = 1 << 20; - break; - case TLB_WORD0_SIZE_16MB: - tlb_size = 16 << 20; - break; - case TLB_WORD0_SIZE_256MB: - tlb_size = 256 << 20; - break; - } - - /* - * Now check the end-address if it's in the range - */ - if ((tlb_vaddr + tlb_size - 1) <= (vaddr + size - 1)) - /* - * Found a TLB in the range. - * Disable it by writing 0 to tlb0 word. - */ - mttlb1(i, 0); - } - } - - /* Execute an ISYNC instruction so that the new TLB entry takes effect */ - asm("isync"); -} - -/* - * Change the I attribute (cache inhibited) of a TLB or multiple TLB's. - * This function is used to either turn cache on or off in a specific - * memory area. - */ -void change_tlb(u32 vaddr, u32 size, u32 tlb_word2_i_value) -{ - int i; - u32 tlb_word0_value; - u32 tlb_word2_value; - u32 tlb_vaddr; - u32 tlb_size = 0; - - for (i=0; i<PPC4XX_TLB_SIZE; i++) { - tlb_word0_value = mftlb1(i); - tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value); - if (((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_ENABLE) && - (tlb_vaddr >= vaddr)) { - /* - * TLB is enabled and start address is lower or equal - * than the area we are looking for. Now we only have - * to check the size/end address for a match. - */ - switch (tlb_word0_value & TLB_WORD0_SIZE_MASK) { - case TLB_WORD0_SIZE_1KB: - tlb_size = 1 << 10; - break; - case TLB_WORD0_SIZE_4KB: - tlb_size = 4 << 10; - break; - case TLB_WORD0_SIZE_16KB: - tlb_size = 16 << 10; - break; - case TLB_WORD0_SIZE_64KB: - tlb_size = 64 << 10; - break; - case TLB_WORD0_SIZE_256KB: - tlb_size = 256 << 10; - break; - case TLB_WORD0_SIZE_1MB: - tlb_size = 1 << 20; - break; - case TLB_WORD0_SIZE_16MB: - tlb_size = 16 << 20; - break; - case TLB_WORD0_SIZE_256MB: - tlb_size = 256 << 20; - break; - } - - /* - * Now check the end-address if it's in the range - */ - if (((tlb_vaddr + tlb_size - 1) <= (vaddr + size - 1)) || - ((tlb_vaddr < (vaddr + size - 1)) && - ((tlb_vaddr + tlb_size - 1) > (vaddr + size - 1)))) { - /* - * Found a TLB in the range. - * Change cache attribute in tlb2 word. - */ - tlb_word2_value = - TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE | - TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE | - TLB_WORD2_W_DISABLE | tlb_word2_i_value | - TLB_WORD2_M_DISABLE | TLB_WORD2_G_DISABLE | - TLB_WORD2_E_DISABLE | TLB_WORD2_UX_ENABLE | - TLB_WORD2_UW_ENABLE | TLB_WORD2_UR_ENABLE | - TLB_WORD2_SX_ENABLE | TLB_WORD2_SW_ENABLE | - TLB_WORD2_SR_ENABLE; - - /* - * Now either flush or invalidate the dcache - */ - if (tlb_word2_i_value) - flush_dcache(); - else - invalidate_dcache(); - - mttlb3(i, tlb_word2_value); - asm("iccci 0,0"); - } - } - } - - /* Execute an ISYNC instruction so that the new TLB entry takes effect */ - asm("isync"); -} - -static int add_tlb_entry(u64 phys_addr, - u32 virt_addr, - u32 tlb_word0_size_value, - u32 tlb_word2_i_value) -{ - int i; - unsigned long tlb_word0_value; - unsigned long tlb_word1_value; - unsigned long tlb_word2_value; - - /* First, find the index of a TLB entry not being used */ - for (i=0; i<PPC4XX_TLB_SIZE; i++) { - tlb_word0_value = mftlb1(i); - if ((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_DISABLE) - break; - } - if (i >= PPC4XX_TLB_SIZE) - return -1; - - /* Second, create the TLB entry */ - tlb_word0_value = TLB_WORD0_EPN_ENCODE(virt_addr) | TLB_WORD0_V_ENABLE | - TLB_WORD0_TS_0 | tlb_word0_size_value; - tlb_word1_value = TLB_WORD1_RPN_ENCODE((u32)phys_addr) | - TLB_WORD1_ERPN_ENCODE(phys_addr >> 32); - tlb_word2_value = TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE | - TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE | - TLB_WORD2_W_DISABLE | tlb_word2_i_value | - TLB_WORD2_M_DISABLE | TLB_WORD2_G_DISABLE | - TLB_WORD2_E_DISABLE | TLB_WORD2_UX_ENABLE | - TLB_WORD2_UW_ENABLE | TLB_WORD2_UR_ENABLE | - TLB_WORD2_SX_ENABLE | TLB_WORD2_SW_ENABLE | - TLB_WORD2_SR_ENABLE; - - /* Wait for all memory accesses to complete */ - sync(); - - /* Third, add the TLB entries */ - mttlb1(i, tlb_word0_value); - mttlb2(i, tlb_word1_value); - mttlb3(i, tlb_word2_value); - - /* Execute an ISYNC instruction so that the new TLB entry takes effect */ - asm("isync"); - - return 0; -} - -static void program_tlb_addr(u64 phys_addr, - u32 virt_addr, - u32 mem_size, - u32 tlb_word2_i_value) -{ - int rc; - int tlb_i; - - tlb_i = tlb_word2_i_value; - while (mem_size != 0) { - rc = 0; - /* Add the TLB entries in to map the region. */ - if (((phys_addr & TLB_256MB_ALIGN_MASK) == phys_addr) && - (mem_size >= TLB_256MB_SIZE)) { - /* Add a 256MB TLB entry */ - if ((rc = add_tlb_entry(phys_addr, virt_addr, - TLB_WORD0_SIZE_256MB, tlb_i)) == 0) { - mem_size -= TLB_256MB_SIZE; - phys_addr += TLB_256MB_SIZE; - virt_addr += TLB_256MB_SIZE; - } - } else if (((phys_addr & TLB_16MB_ALIGN_MASK) == phys_addr) && - (mem_size >= TLB_16MB_SIZE)) { - /* Add a 16MB TLB entry */ - if ((rc = add_tlb_entry(phys_addr, virt_addr, - TLB_WORD0_SIZE_16MB, tlb_i)) == 0) { - mem_size -= TLB_16MB_SIZE; - phys_addr += TLB_16MB_SIZE; - virt_addr += TLB_16MB_SIZE; - } - } else if (((phys_addr & TLB_1MB_ALIGN_MASK) == phys_addr) && - (mem_size >= TLB_1MB_SIZE)) { - /* Add a 1MB TLB entry */ - if ((rc = add_tlb_entry(phys_addr, virt_addr, - TLB_WORD0_SIZE_1MB, tlb_i)) == 0) { - mem_size -= TLB_1MB_SIZE; - phys_addr += TLB_1MB_SIZE; - virt_addr += TLB_1MB_SIZE; - } - } else if (((phys_addr & TLB_256KB_ALIGN_MASK) == phys_addr) && - (mem_size >= TLB_256KB_SIZE)) { - /* Add a 256KB TLB entry */ - if ((rc = add_tlb_entry(phys_addr, virt_addr, - TLB_WORD0_SIZE_256KB, tlb_i)) == 0) { - mem_size -= TLB_256KB_SIZE; - phys_addr += TLB_256KB_SIZE; - virt_addr += TLB_256KB_SIZE; - } - } else if (((phys_addr & TLB_64KB_ALIGN_MASK) == phys_addr) && - (mem_size >= TLB_64KB_SIZE)) { - /* Add a 64KB TLB entry */ - if ((rc = add_tlb_entry(phys_addr, virt_addr, - TLB_WORD0_SIZE_64KB, tlb_i)) == 0) { - mem_size -= TLB_64KB_SIZE; - phys_addr += TLB_64KB_SIZE; - virt_addr += TLB_64KB_SIZE; - } - } else if (((phys_addr & TLB_16KB_ALIGN_MASK) == phys_addr) && - (mem_size >= TLB_16KB_SIZE)) { - /* Add a 16KB TLB entry */ - if ((rc = add_tlb_entry(phys_addr, virt_addr, - TLB_WORD0_SIZE_16KB, tlb_i)) == 0) { - mem_size -= TLB_16KB_SIZE; - phys_addr += TLB_16KB_SIZE; - virt_addr += TLB_16KB_SIZE; - } - } else if (((phys_addr & TLB_4KB_ALIGN_MASK) == phys_addr) && - (mem_size >= TLB_4KB_SIZE)) { - /* Add a 4KB TLB entry */ - if ((rc = add_tlb_entry(phys_addr, virt_addr, - TLB_WORD0_SIZE_4KB, tlb_i)) == 0) { - mem_size -= TLB_4KB_SIZE; - phys_addr += TLB_4KB_SIZE; - virt_addr += TLB_4KB_SIZE; - } - } else if (((phys_addr & TLB_1KB_ALIGN_MASK) == phys_addr) && - (mem_size >= TLB_1KB_SIZE)) { - /* Add a 1KB TLB entry */ - if ((rc = add_tlb_entry(phys_addr, virt_addr, - TLB_WORD0_SIZE_1KB, tlb_i)) == 0) { - mem_size -= TLB_1KB_SIZE; - phys_addr += TLB_1KB_SIZE; - virt_addr += TLB_1KB_SIZE; - } - } else { - printf("ERROR: no TLB size exists for the base address 0x%llx.\n", - phys_addr); - } - - if (rc != 0) - printf("ERROR: no TLB entries available for the base addr 0x%llx.\n", - phys_addr); - } - - return; -} - -/* - * Program one (or multiple) TLB entries for one memory region - * - * Common usage for boards with SDRAM DIMM modules to dynamically - * configure the TLB's for the SDRAM - */ -void program_tlb(u64 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value) -{ - region_t region_array; - - region_array.base = phys_addr; - region_array.size = size; - region_array.tlb_word2_i_value = tlb_word2_i_value; /* en-/disable cache */ - - /* Call the routine to add in the tlb entries for the memory regions */ - program_tlb_addr(region_array.base, virt_addr, region_array.size, - region_array.tlb_word2_i_value); - - return; -} - -#endif /* CONFIG_440 */ diff --git a/arch/powerpc/cpu/ppc4xx/traps.c b/arch/powerpc/cpu/ppc4xx/traps.c deleted file mode 100644 index 9baa7a1..0000000 --- a/arch/powerpc/cpu/ppc4xx/traps.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * linux/arch/powerpc/kernel/traps.c - * - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * - * Modified by Cort Dougan (cort@cs.nmt.edu) - * and Paul Mackerras (paulus@cs.anu.edu.au) - * - * (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 - */ - -/* - * This file handles the architecture-dependent parts of hardware exceptions - */ - -#include <common.h> -#include <command.h> -#include <kgdb.h> -#include <asm/processor.h> - -DECLARE_GLOBAL_DATA_PTR; - -/* Returns 0 if exception not found and fixup otherwise. */ -extern unsigned long search_exception_table(unsigned long); - -/* THIS NEEDS CHANGING to use the board info structure. - */ -#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize) - -static __inline__ unsigned long get_esr(void) -{ - unsigned long val; - -#if defined(CONFIG_440) - asm volatile("mfspr %0, 0x03e" : "=r" (val) :); -#else - asm volatile("mfesr %0" : "=r" (val) :); -#endif - return val; -} - -#define ESR_MCI 0x80000000 -#define ESR_PIL 0x08000000 -#define ESR_PPR 0x04000000 -#define ESR_PTR 0x02000000 -#define ESR_DST 0x00800000 -#define ESR_DIZ 0x00400000 -#define ESR_U0F 0x00008000 - -#if defined(CONFIG_CMD_BEDBUG) -extern void do_bedbug_breakpoint(struct pt_regs *); -#endif - -/* - * Trap & Exception support - */ - -void -print_backtrace(unsigned long *sp) -{ - int cnt = 0; - unsigned long i; - - printf("Call backtrace: "); - while (sp) { - if ((uint)sp > END_OF_MEM) - break; - - i = sp[1]; - if (cnt++ % 7 == 0) - printf("\n"); - printf("%08lX ", i); - if (cnt > 32) break; - sp = (unsigned long *)*sp; - } - printf("\n"); -} - -void show_regs(struct pt_regs * regs) -{ - int i; - - printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n", - regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar); - printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", - regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, - regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, - regs->msr&MSR_IR ? 1 : 0, - regs->msr&MSR_DR ? 1 : 0); - - printf("\n"); - for (i = 0; i < 32; i++) { - if ((i % 8) == 0) { - printf("GPR%02d: ", i); - } - - printf("%08lX ", regs->gpr[i]); - if ((i % 8) == 7) { - printf("\n"); - } - } -} - - -void -_exception(int signr, struct pt_regs *regs) -{ - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Exception"); -} - -void -MachineCheckException(struct pt_regs *regs) -{ - unsigned long fixup, val; -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - u32 value2; - int corr_ecc = 0; - int uncorr_ecc = 0; -#endif - - if ((fixup = search_exception_table(regs->nip)) != 0) { - regs->nip = fixup; - val = mfspr(MCSR); - /* Clear MCSR */ - mtspr(SPRN_MCSR, val); - return; - } - -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - - printf("Machine Check Exception.\n"); - printf("Caused by (from msr): "); - printf("regs %p ", regs); - - val = get_esr(); - -#if !defined(CONFIG_440) && !defined(CONFIG_405EX) - if (val& ESR_IMCP) { - printf("Instruction"); - mtspr(ESR, val & ~ESR_IMCP); - } else { - printf("Data"); - } - printf(" machine check.\n"); - -#elif defined(CONFIG_440) || defined(CONFIG_405EX) - if (val& ESR_IMCP){ - printf("Instruction Synchronous Machine Check exception\n"); - mtspr(SPRN_ESR, val & ~ESR_IMCP); - } else { - val = mfspr(MCSR); - if (val & MCSR_IB) - printf("Instruction Read PLB Error\n"); -#if defined(CONFIG_440) - if (val & MCSR_DRB) - printf("Data Read PLB Error\n"); - if (val & MCSR_DWB) - printf("Data Write PLB Error\n"); -#else - if (val & MCSR_DB) - printf("Data PLB Error\n"); -#endif - if (val & MCSR_TLBP) - printf("TLB Parity Error\n"); - if (val & MCSR_ICP){ - /*flush_instruction_cache(); */ - printf("I-Cache Parity Error\n"); - } - if (val & MCSR_DCSP) - printf("D-Cache Search Parity Error\n"); - if (val & MCSR_DCFP) - printf("D-Cache Flush Parity Error\n"); - if (val & MCSR_IMPE) - printf("Machine Check exception is imprecise\n"); - - /* Clear MCSR */ - mtspr(SPRN_MCSR, val); - } - -#if defined(CONFIG_DDR_ECC) && defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) - /* - * Read and print ECC status register/info: - * The faulting address is only known upon uncorrectable ECC - * errors. - */ - mfsdram(SDRAM_ECCES, val); - if (val & SDRAM_ECCES_CE) - printf("ECC: Correctable error\n"); - if (val & SDRAM_ECCES_UE) { - printf("ECC: Uncorrectable error at 0x%02x%08x\n", - mfdcr(SDRAM_ERRADDULL), mfdcr(SDRAM_ERRADDLLL)); - } -#endif /* CONFIG_DDR_ECC ... */ - -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - mfsdram(DDR0_00, val) ; - printf("DDR0: DDR0_00 %lx\n", val); - val = (val >> 16) & 0xff; - if (val & 0x80) - printf("DDR0: At least one interrupt active\n"); - if (val & 0x40) - printf("DDR0: DRAM initialization complete.\n"); - if (val & 0x20) { - printf("DDR0: Multiple uncorrectable ECC events.\n"); - uncorr_ecc = 1; - } - if (val & 0x10) { - printf("DDR0: Single uncorrectable ECC event.\n"); - uncorr_ecc = 1; - } - if (val & 0x08) { - printf("DDR0: Multiple correctable ECC events.\n"); - corr_ecc = 1; - } - if (val & 0x04) { - printf("DDR0: Single correctable ECC event.\n"); - corr_ecc = 1; - } - if (val & 0x02) - printf("Multiple accesses outside the defined" - " physical memory space detected\n"); - if (val & 0x01) - printf("DDR0: Single access outside the defined" - " physical memory space detected.\n"); - - mfsdram(DDR0_01, val); - val = (val >> 8) & 0x7; - switch (val ) { - case 0: - printf("DDR0: Write Out-of-Range command\n"); - break; - case 1: - printf("DDR0: Read Out-of-Range command\n"); - break; - case 2: - printf("DDR0: Masked write Out-of-Range command\n"); - break; - case 4: - printf("DDR0: Wrap write Out-of-Range command\n"); - break; - case 5: - printf("DDR0: Wrap read Out-of-Range command\n"); - break; - default: - mfsdram(DDR0_01, value2); - printf("DDR0: No DDR0 error know 0x%lx %x\n", val, value2); - } - mfsdram(DDR0_23, val); - if (((val >> 16) & 0xff) && corr_ecc) - printf("DDR0: Syndrome for correctable ECC event 0x%lx\n", - (val >> 16) & 0xff); - mfsdram(DDR0_23, val); - if (((val >> 8) & 0xff) && uncorr_ecc) - printf("DDR0: Syndrome for uncorrectable ECC event 0x%lx\n", - (val >> 8) & 0xff); - mfsdram(DDR0_33, val); - if (val) - printf("DDR0: Address of command that caused an " - "Out-of-Range interrupt %lx\n", val); - mfsdram(DDR0_34, val); - if (val && uncorr_ecc) - printf("DDR0: Address of uncorrectable ECC event %lx\n", val); - mfsdram(DDR0_35, val); - if (val && uncorr_ecc) - printf("DDR0: Address of uncorrectable ECC event %lx\n", val); - mfsdram(DDR0_36, val); - if (val && uncorr_ecc) - printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val); - mfsdram(DDR0_37, val); - if (val && uncorr_ecc) - printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val); - mfsdram(DDR0_38, val); - if (val && corr_ecc) - printf("DDR0: Address of correctable ECC event %lx\n", val); - mfsdram(DDR0_39, val); - if (val && corr_ecc) - printf("DDR0: Address of correctable ECC event %lx\n", val); - mfsdram(DDR0_40, val); - if (val && corr_ecc) - printf("DDR0: Data of correctable ECC event 0x%08lx\n", val); - mfsdram(DDR0_41, val); - if (val && corr_ecc) - printf("DDR0: Data of correctable ECC event 0x%08lx\n", val); -#endif /* CONFIG_440EPX */ -#endif /* CONFIG_440 */ - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); - panic("machine check"); -} - -void -AlignmentException(struct pt_regs *regs) -{ -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - - show_regs(regs); - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Alignment Exception"); -} - -void -ProgramCheckException(struct pt_regs *regs) -{ - long esr_val; - -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - - show_regs(regs); - - esr_val = get_esr(); - if( esr_val & ESR_PIL ) - printf( "** Illegal Instruction **\n" ); - else if( esr_val & ESR_PPR ) - printf( "** Privileged Instruction **\n" ); - else if( esr_val & ESR_PTR ) - printf( "** Trap Instruction **\n" ); - - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Program Check Exception"); -} - -void -DecrementerPITException(struct pt_regs *regs) -{ - /* - * Reset PIT interrupt - */ - mtspr(SPRN_TSR, 0x08000000); - - /* - * Call timer_interrupt routine in interrupts.c - */ - timer_interrupt(NULL); -} - - -void -UnknownException(struct pt_regs *regs) -{ -#if defined(CONFIG_CMD_KGDB) - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - return; -#endif - - printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", - regs->nip, regs->msr, regs->trap); - _exception(0, regs); -} - -void -DebugException(struct pt_regs *regs) -{ - printf("Debugger trap at @ %lx\n", regs->nip ); - show_regs(regs); -#if defined(CONFIG_CMD_BEDBUG) - do_bedbug_breakpoint( regs ); -#endif -} - -/* Probe an address by reading. If not present, return -1, otherwise - * return 0. - */ -int -addr_probe(uint *addr) -{ -#if 0 - int retval; - - __asm__ __volatile__( \ - "1: lwz %0,0(%1)\n" \ - " eieio\n" \ - " li %0,0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,-1\n" \ - " b 2b\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,3b\n" \ - ".text" \ - : "=r" (retval) : "r"(addr)); - - return (retval); -#endif - return 0; -} diff --git a/arch/powerpc/cpu/ppc4xx/u-boot.lds b/arch/powerpc/cpu/ppc4xx/u-boot.lds deleted file mode 100644 index 656f59a..0000000 --- a/arch/powerpc/cpu/ppc4xx/u-boot.lds +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2007-2009 Freescale Semiconductor, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include "config.h" /* CONFIG_BOARDDIR */ - -#ifndef RESET_VECTOR_ADDRESS -#ifdef CONFIG_RESET_VECTOR_ADDRESS -#define RESET_VECTOR_ADDRESS CONFIG_RESET_VECTOR_ADDRESS -#else -#define RESET_VECTOR_ADDRESS 0xfffffffc -#endif -#endif - -OUTPUT_ARCH(powerpc) - -PHDRS -{ - text PT_LOAD; - bss PT_LOAD; -} - -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = + SIZEOF_HEADERS; - .text : - { - *(.text*) - } :text - _etext = .; - PROVIDE (etext = .); - .rodata : - { - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) - } :text - - /* Read-write section, merged into data segment: */ - . = (. + 0x00FF) & 0xFFFFFF00; - _erotext = .; - PROVIDE (erotext = .); - .reloc : - { - _GOT2_TABLE_ = .; - KEEP(*(.got2)) - KEEP(*(.got)) - PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4); - _FIXUP_TABLE_ = .; - KEEP(*(.fixup)) - } - __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1; - __fixup_entries = (. - _FIXUP_TABLE_) >> 2; - - .data : - { - *(.data*) - *(.sdata*) - } - _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(256); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(256); - __init_end = .; - -#ifdef CONFIG_440 - .bootpg RESET_VECTOR_ADDRESS - 0xffc : - { - arch/powerpc/cpu/ppc4xx/start.o (.bootpg) - - /* - * PPC440 board need a board specific object with the - * TLB definitions. This needs to get included right after - * start.o, since the first shadow TLB only covers 4k - * of address space. - */ -#ifdef CONFIG_INIT_TLB - CONFIG_INIT_TLB (.bootpg) -#else - CONFIG_BOARDDIR/init.o (.bootpg) -#endif - } :text = 0xffff -#endif - - .resetvec RESET_VECTOR_ADDRESS : - { - KEEP(*(.resetvec)) - } :text = 0xffff - - . = RESET_VECTOR_ADDRESS + 0x4; - - /* - * Make sure that the bss segment isn't linked at 0x0, otherwise its - * address won't be updated during relocation fixups. Note that - * this is a temporary fix. Code to dynamically the fixup the bss - * location will be added in the future. When the bss relocation - * fixup code is present this workaround should be removed. - */ -#if (RESET_VECTOR_ADDRESS == 0xfffffffc) - . |= 0x10; -#endif - - __bss_start = .; - .bss (NOLOAD) : - { - *(.bss*) - *(.sbss*) - *(COMMON) - } :bss - - . = ALIGN(4); - _end = . ; - PROVIDE (end = .); -} diff --git a/arch/powerpc/cpu/ppc4xx/uic.c b/arch/powerpc/cpu/ppc4xx/uic.c deleted file mode 100644 index 324f0e9..0000000 --- a/arch/powerpc/cpu/ppc4xx/uic.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * (C) Copyright 2000-2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2002 (440 port) - * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com - * - * (C) Copyright 2003 (440GX port) - * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com - * - * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX) - * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es - * Work supported by Qtechnology (htpp://qtec.com) - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <watchdog.h> -#include <command.h> -#include <asm/processor.h> -#include <asm/interrupt.h> -#include <asm/ppc4xx.h> -#include <ppc_asm.tmpl> -#include <commproc.h> - -#if (UIC_MAX > 3) -#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \ - UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI) | \ - UIC_MASK(VECNUM_UIC3CI) | UIC_MASK(VECNUM_UIC3NCI)) -#elif (UIC_MAX > 2) -#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \ - UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI)) -#elif (UIC_MAX > 1) -#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI)) -#else -#define UICB0_ALL 0 -#endif - -u32 get_dcr(u16); - -DECLARE_GLOBAL_DATA_PTR; - -void pic_enable(void) -{ -#if (UIC_MAX > 1) - /* Install the UIC1 handlers */ - irq_install_handler(VECNUM_UIC1NCI, (void *)(void *)external_interrupt, 0); - irq_install_handler(VECNUM_UIC1CI, (void *)(void *)external_interrupt, 0); -#endif -#if (UIC_MAX > 2) - irq_install_handler(VECNUM_UIC2NCI, (void *)(void *)external_interrupt, 0); - irq_install_handler(VECNUM_UIC2CI, (void *)(void *)external_interrupt, 0); -#endif -#if (UIC_MAX > 3) - irq_install_handler(VECNUM_UIC3NCI, (void *)(void *)external_interrupt, 0); - irq_install_handler(VECNUM_UIC3CI, (void *)(void *)external_interrupt, 0); -#endif -} - -/* Handler for UIC interrupt */ -static void uic_interrupt(u32 uic_base, int vec_base) -{ - u32 uic_msr; - u32 msr_shift; - int vec; - - /* - * Read masked interrupt status register to determine interrupt source - */ - uic_msr = get_dcr(uic_base + UIC_MSR); - msr_shift = uic_msr; - vec = vec_base; - - while (msr_shift != 0) { - if (msr_shift & 0x80000000) - interrupt_run_handler(vec); - /* - * Shift msr to next position and increment vector - */ - msr_shift <<= 1; - vec++; - } -} - -/* - * Handle external interrupts - */ -void external_interrupt(struct pt_regs *regs) -{ - u32 uic_msr; - - /* - * Read masked interrupt status register to determine interrupt source - */ - uic_msr = mfdcr(UIC0MSR); - -#if (UIC_MAX > 1) - if ((UIC_MASK(VECNUM_UIC1CI) & uic_msr) || - (UIC_MASK(VECNUM_UIC1NCI) & uic_msr)) - uic_interrupt(UIC1_DCR_BASE, 32); -#endif - -#if (UIC_MAX > 2) - if ((UIC_MASK(VECNUM_UIC2CI) & uic_msr) || - (UIC_MASK(VECNUM_UIC2NCI) & uic_msr)) - uic_interrupt(UIC2_DCR_BASE, 64); -#endif - -#if (UIC_MAX > 3) - if ((UIC_MASK(VECNUM_UIC3CI) & uic_msr) || - (UIC_MASK(VECNUM_UIC3NCI) & uic_msr)) - uic_interrupt(UIC3_DCR_BASE, 96); -#endif - - mtdcr(UIC0SR, (uic_msr & UICB0_ALL)); - - if (uic_msr & ~(UICB0_ALL)) - uic_interrupt(UIC0_DCR_BASE, 0); - - return; -} - -void pic_irq_ack(unsigned int vec) -{ - if ((vec >= 0) && (vec < 32)) - mtdcr(UIC0SR, UIC_MASK(vec)); - else if ((vec >= 32) && (vec < 64)) - mtdcr(UIC1SR, UIC_MASK(vec)); - else if ((vec >= 64) && (vec < 96)) - mtdcr(UIC2SR, UIC_MASK(vec)); - else if (vec >= 96) - mtdcr(UIC3SR, UIC_MASK(vec)); -} - -/* - * Install and free a interrupt handler. - */ -void pic_irq_enable(unsigned int vec) -{ - - if ((vec >= 0) && (vec < 32)) - mtdcr(UIC0ER, mfdcr(UIC0ER) | UIC_MASK(vec)); - else if ((vec >= 32) && (vec < 64)) - mtdcr(UIC1ER, mfdcr(UIC1ER) | UIC_MASK(vec)); - else if ((vec >= 64) && (vec < 96)) - mtdcr(UIC2ER, mfdcr(UIC2ER) | UIC_MASK(vec)); - else if (vec >= 96) - mtdcr(UIC3ER, mfdcr(UIC3ER) | UIC_MASK(vec)); - - debug("Install interrupt vector %d\n", vec); -} - -void pic_irq_disable(unsigned int vec) -{ - if ((vec >= 0) && (vec < 32)) - mtdcr(UIC0ER, mfdcr(UIC0ER) & ~UIC_MASK(vec)); - else if ((vec >= 32) && (vec < 64)) - mtdcr(UIC1ER, mfdcr(UIC1ER) & ~UIC_MASK(vec)); - else if ((vec >= 64) && (vec < 96)) - mtdcr(UIC2ER, mfdcr(UIC2ER) & ~UIC_MASK(vec)); - else if (vec >= 96) - mtdcr(UIC3ER, mfdcr(UIC3ER) & ~UIC_MASK(vec)); -} diff --git a/arch/powerpc/cpu/ppc4xx/usb.c b/arch/powerpc/cpu/ppc4xx/usb.c deleted file mode 100644 index 592efe7..0000000 --- a/arch/powerpc/cpu/ppc4xx/usb.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * (C) Copyright 2007 - * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> - -#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) - -#ifdef CONFIG_4xx_DCACHE -#include <asm/mmu.h> -DECLARE_GLOBAL_DATA_PTR; -#endif - -#include "usbdev.h" - -int usb_cpu_init(void) -{ -#ifdef CONFIG_4xx_DCACHE - /* disable cache */ - change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE); -#endif - -#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) - usb_dev_init(); -#endif - return 0; -} - -int usb_cpu_stop(void) -{ -#ifdef CONFIG_4xx_DCACHE - /* enable cache */ - change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0); -#endif - return 0; -} - -int usb_cpu_init_fail(void) -{ -#ifdef CONFIG_4xx_DCACHE - /* enable cache */ - change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0); -#endif - return 0; -} - -#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */ diff --git a/arch/powerpc/cpu/ppc4xx/usb_ohci.c b/arch/powerpc/cpu/ppc4xx/usb_ohci.c deleted file mode 100644 index a9edacd..0000000 --- a/arch/powerpc/cpu/ppc4xx/usb_ohci.c +++ /dev/null @@ -1,1648 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB on the PPC440EP. - * - * (C) Copyright 2003-2004 - * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> - * - * (C) Copyright 2004 - * Pierre Aubert, Staubli Faverges <p.aubert@staubli.com> - * - * Note: Much of this code has been derived from Linux 2.4 - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell - * - * 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 - * - */ -/* - * IMPORTANT NOTES - * 1 - this driver is intended for use with USB Mass Storage Devices - * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! - */ - -#include <common.h> - -#ifdef CONFIG_USB_OHCI - -#include <malloc.h> -#include <usb.h> -#include "usb_ohci.h" - -#include "usbdev.h" - -#define OHCI_USE_NPS /* force NoPowerSwitching mode */ -#undef OHCI_VERBOSE_DEBUG /* not always helpful */ -#undef DEBUG -#undef SHOW_INFO -#undef OHCI_FILL_TRACE - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE - -#define readl(a) (*((volatile u32 *)(a))) -#define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a)) - -#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) - -#ifdef DEBUG -#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) -#else -#define dbg(format, arg...) do {} while(0) -#endif /* DEBUG */ -#define err(format, arg...) printf("ERROR: " format "\n", ## arg) -#ifdef SHOW_INFO -#define info(format, arg...) printf("INFO: " format "\n", ## arg) -#else -#define info(format, arg...) do {} while(0) -#endif - -#define m16_swap(x) swap_16(x) -#define m32_swap(x) swap_32(x) - -#if defined(CONFIG_405EZ) || defined(CONFIG_440EP) || defined(CONFIG_440EPX) -#define ohci_cpu_to_le16(x) (x) -#define ohci_cpu_to_le32(x) (x) -#else -#define ohci_cpu_to_le16(x) swap_16(x) -#define ohci_cpu_to_le32(x) swap_32(x) -#endif - -/* global ohci_t */ -static ohci_t gohci; -/* this must be aligned to a 256 byte boundary */ -struct ohci_hcca ghcca[1]; -/* a pointer to the aligned storage */ -struct ohci_hcca *phcca; -/* this allocates EDs for all possible endpoints */ -struct ohci_device ohci_dev; -/* urb_priv */ -urb_priv_t urb_priv; -/* RHSC flag */ -int got_rhsc; -/* device which was disconnected */ -struct usb_device *devgone; -/* flag guarding URB transation */ -int urb_finished = 0; - -/*-------------------------------------------------------------------------*/ - -/* AMD-756 (D2 rev) reports corrupt register contents in some cases. - * The erratum (#4) description is incorrect. AMD's workaround waits - * till some bits (mostly reserved) are clear; ok for all revs. - */ -#define OHCI_QUIRK_AMD756 0xabcd -#define read_roothub(hc, register, mask) ({ \ - u32 temp = readl (&hc->regs->roothub.register); \ - if (hc->flags & OHCI_QUIRK_AMD756) \ - while (temp & mask) \ - temp = readl (&hc->regs->roothub.register); \ - temp; }) - -static u32 roothub_a (struct ohci *hc) - { return read_roothub (hc, a, 0xfc0fe000); } -static inline u32 roothub_b (struct ohci *hc) - { return readl (&hc->regs->roothub.b); } -static inline u32 roothub_status (struct ohci *hc) - { return readl (&hc->regs->roothub.status); } -static u32 roothub_portstatus (struct ohci *hc, int i) - { return read_roothub (hc, portstatus [i], 0xffe0fce0); } - - -/* forward declaration */ -static int hc_interrupt (void); -static void -td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, - int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval); - -/*-------------------------------------------------------------------------* - * URB support functions - *-------------------------------------------------------------------------*/ - -/* free HCD-private data associated with this URB */ - -static void urb_free_priv (urb_priv_t * urb) -{ - int i; - int last; - struct td * td; - - last = urb->length - 1; - if (last >= 0) { - for (i = 0; i <= last; i++) { - td = urb->td[i]; - if (td) { - td->usb_dev = NULL; - urb->td[i] = NULL; - } - } - } -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -static int sohci_get_current_frame_number (struct usb_device * dev); - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header */ - -static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer, - int transfer_len, struct devrequest * setup, char * str, int small) -{ - urb_priv_t * purb = &urb_priv; - - dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", - str, - sohci_get_current_frame_number (dev), - usb_pipedevice (pipe), - usb_pipeendpoint (pipe), - usb_pipeout (pipe)? 'O': 'I', - usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): - (usb_pipecontrol (pipe)? "CTRL": "BULK"), - purb->actual_length, - transfer_len, dev->status); -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol (pipe)) { - printf (__FILE__ ": cmd(8):"); - for (i = 0; i < 8 ; i++) - printf (" %02x", ((__u8 *) setup) [i]); - printf ("\n"); - } - if (transfer_len > 0 && buffer) { - printf (__FILE__ ": data(%d/%d):", - purb->actual_length, - transfer_len); - len = usb_pipeout (pipe)? - transfer_len: purb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printf (" %02x", ((__u8 *) buffer) [i]); - printf ("%s\n", i < len? "...": ""); - } - } -#endif -} - -/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ -void ep_print_int_eds (ohci_t *ohci, char * str) { - int i, j; - __u32 * ed_p; - for (i= 0; i < 32; i++) { - j = 5; - ed_p = &(ohci->hcca->int_table [i]); - if (*ed_p == 0) - continue; - printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); - while (*ed_p != 0 && j--) { - ed_t *ed = (ed_t *)ohci_cpu_to_le32(ed_p); - printf (" ed: %4x;", ed->hwINFO); - ed_p = &ed->hwNextED; - } - printf ("\n"); - } -} - -static void ohci_dump_intr_mask (char *label, __u32 mask) -{ - dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : "" - ); -} - -static void maybe_print_eds (char *label, __u32 value) -{ - ed_t *edp = (ed_t *)value; - - if (value) { - dbg ("%s %08x", label, value); - dbg ("%08x", edp->hwINFO); - dbg ("%08x", edp->hwTailP); - dbg ("%08x", edp->hwHeadP); - dbg ("%08x", edp->hwNextED); - } -} - -static char * hcfs2string (int state) -{ - switch (state) { - case OHCI_USB_RESET: return "reset"; - case OHCI_USB_RESUME: return "resume"; - case OHCI_USB_OPER: return "operational"; - case OHCI_USB_SUSPEND: return "suspend"; - } - return "?"; -} - -/* dump control and status registers */ -static void ohci_dump_status (ohci_t *controller) -{ - struct ohci_regs *regs = controller->regs; - __u32 temp; - - temp = readl (®s->revision) & 0xff; - if (temp != 0x10) - dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); - - temp = readl (®s->control); - dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string (temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", - temp & OHCI_CTRL_CBSR - ); - - temp = readl (®s->cmdstatus); - dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", - (temp & OHCI_HCR) ? " HCR" : "" - ); - - ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); - ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); - - maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); - - maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); - maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); - - maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); - maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); - - maybe_print_eds ("donehead", readl (®s->donehead)); -} - -static void ohci_dump_roothub (ohci_t *controller, int verbose) -{ - __u32 temp, ndp, i; - - temp = roothub_a (controller); - ndp = (temp & RH_A_NDP); - - if (verbose) { - dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", - ndp - ); - temp = roothub_b (controller); - dbg ("roothub.b: %08x PPCM=%04x DR=%04x", - temp, - (temp & RH_B_PPCM) >> 16, - (temp & RH_B_DR) - ); - temp = roothub_status (controller); - dbg ("roothub.status: %08x%s%s%s%s%s%s", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : "" - ); - } - - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus (controller, i); - dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", - i, - temp, - (temp & RH_PS_PRSC) ? " PRSC" : "", - (temp & RH_PS_OCIC) ? " OCIC" : "", - (temp & RH_PS_PSSC) ? " PSSC" : "", - (temp & RH_PS_PESC) ? " PESC" : "", - (temp & RH_PS_CSC) ? " CSC" : "", - - (temp & RH_PS_LSDA) ? " LSDA" : "", - (temp & RH_PS_PPS) ? " PPS" : "", - (temp & RH_PS_PRS) ? " PRS" : "", - (temp & RH_PS_POCI) ? " POCI" : "", - (temp & RH_PS_PSS) ? " PSS" : "", - - (temp & RH_PS_PES) ? " PES" : "", - (temp & RH_PS_CCS) ? " CCS" : "" - ); - } -} - -static void ohci_dump (ohci_t *controller, int verbose) -{ - dbg ("OHCI controller usb-%s state", controller->slot_name); - - /* dumps some of the state we know about */ - ohci_dump_status (controller); - if (verbose) - ep_print_int_eds (controller, "hcca"); - dbg ("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub (controller, 1); -} - - -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------* - * Interface functions (URB) - *-------------------------------------------------------------------------*/ - -/* get a transfer request */ - -int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) -{ - ohci_t *ohci; - ed_t * ed; - urb_priv_t *purb_priv; - int i, size = 0; - - ohci = &gohci; - - /* when controller's hung, permit only roothub cleanup attempts - * such as powering down ports */ - if (ohci->disabled) { - err("sohci_submit_job: EPIPE"); - return -1; - } - - /* if we have an unfinished URB from previous transaction let's - * fail and scream as quickly as possible so as not to corrupt - * further communication */ - if (!urb_finished) { - err("sohci_submit_job: URB NOT FINISHED"); - return -1; - } - /* we're about to begin a new transaction here so mark the URB unfinished */ - urb_finished = 0; - - /* every endpoint has a ed, locate and fill it */ - if (!(ed = ep_add_ed (dev, pipe))) { - err("sohci_submit_job: ENOMEM"); - return -1; - } - - /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype (pipe)) { - case PIPE_BULK: /* one TD for every 4096 Byte */ - size = (transfer_len - 1) / 4096 + 1; - break; - case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (transfer_len == 0)? 2: - (transfer_len - 1) / 4096 + 3; - break; - } - - if (size >= (N_URB_TD - 1)) { - err("need %d TDs, only have %d", size, N_URB_TD); - return -1; - } - purb_priv = &urb_priv; - purb_priv->pipe = pipe; - - /* fill the private part of the URB */ - purb_priv->length = size; - purb_priv->ed = ed; - purb_priv->actual_length = 0; - - /* allocate the TDs */ - /* note that td[0] was allocated in ep_add_ed */ - for (i = 0; i < size; i++) { - purb_priv->td[i] = td_alloc (dev); - if (!purb_priv->td[i]) { - purb_priv->length = i; - urb_free_priv (purb_priv); - err("sohci_submit_job: ENOMEM"); - return -1; - } - } - - if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv (purb_priv); - err("sohci_submit_job: EINVAL"); - return -1; - } - - /* link the ed into a chain if is not already */ - if (ed->state != ED_OPER) - ep_link (ohci, ed); - - /* fill the TDs and link it to the ed */ - td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -/* tell us the current USB frame number */ - -static int sohci_get_current_frame_number (struct usb_device *usb_dev) -{ - ohci_t *ohci = &gohci; - - return ohci_cpu_to_le16 (ohci->hcca->frame_no); -} -#endif - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* link an ed into one of the HC chains */ - -static int ep_link (ohci_t *ohci, ed_t *edi) -{ - volatile ed_t *ed = edi; - - ed->state = ED_OPER; - - switch (ed->type) { - case PIPE_CONTROL: - ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) { - writel (ed, &ohci->regs->ed_controlhead); - } else { - ohci->ed_controltail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed); - } - ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); - } - ohci->ed_controltail = edi; - break; - - case PIPE_BULK: - ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) { - writel (ed, &ohci->regs->ed_bulkhead); - } else { - ohci->ed_bulktail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed); - } - ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && - !ohci->ed_rm_list[1] && !ohci->sleeping) { - ohci->hc_control |= OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); - } - ohci->ed_bulktail = edi; - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* unlink an ed from one of the HC chains. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed */ - -static int ep_unlink (ohci_t *ohci, ed_t *edi) -{ - volatile ed_t *ed = edi; - - ed->hwINFO |= ohci_cpu_to_le32 (OHCI_ED_SKIP); - - switch (ed->type) { - case PIPE_CONTROL: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); - } - writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_controltail == ed) { - ohci->ed_controltail = ed->ed_prev; - } else { - ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case PIPE_BULK: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); - } - writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead); - } else { - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_bulktail == ed) { - ohci->ed_bulktail = ed->ed_prev; - } else { - ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - } - ed->state = ED_UNLINK; - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, - * but the USB stack is a little bit stateless so we do it at every transaction - * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK - * in all other cases the state is left unchanged - * the ed info fields are setted anyway even though most of them should not change */ - -static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe) -{ - td_t *td; - ed_t *ed_ret; - volatile ed_t *ed; - - ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) | - (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]; - - if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { - err("ep_add_ed: pending delete"); - /* pending delete request */ - return NULL; - } - - if (ed->state == ED_NEW) { - ed->hwINFO = ohci_cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ - /* dummy td; end of td list for ed */ - td = td_alloc (usb_dev); - ed->hwTailP = ohci_cpu_to_le32 ((unsigned long)td); - ed->hwHeadP = ed->hwTailP; - ed->state = ED_UNLINK; - ed->type = usb_pipetype (pipe); - ohci_dev.ed_cnt++; - } - - ed->hwINFO = ohci_cpu_to_le32 (usb_pipedevice (pipe) - | usb_pipeendpoint (pipe) << 7 - | (usb_pipeisoc (pipe)? 0x8000: 0) - | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) - | usb_pipeslow (pipe) << 13 - | usb_maxpacket (usb_dev, pipe) << 16); - - return ed_ret; -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -static void td_fill (ohci_t *ohci, unsigned int info, - void *data, int len, - struct usb_device *dev, int index, urb_priv_t *urb_priv) -{ - volatile td_t *td, *td_pt; -#ifdef OHCI_FILL_TRACE - int i; -#endif - - if (index > urb_priv->length) { - err("index > length"); - return; - } - /* use this td as the next dummy */ - td_pt = urb_priv->td [index]; - td_pt->hwNextTD = 0; - - /* fill the old dummy TD */ - td = urb_priv->td [index] = (td_t *)(ohci_cpu_to_le32 (urb_priv->ed->hwTailP) & ~0xf); - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->data = (__u32)data; -#ifdef OHCI_FILL_TRACE - if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) { - for (i = 0; i < len; i++) - printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]); - printf("\n"); - } -#endif - if (!len) - data = 0; - - td->hwINFO = ohci_cpu_to_le32 (info); - td->hwCBP = ohci_cpu_to_le32 ((unsigned long)data); - if (data) - td->hwBE = ohci_cpu_to_le32 ((unsigned long)(data + len - 1)); - else - td->hwBE = 0; - td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt); - - /* append to queue */ - td->ed->hwTailP = td->hwNextTD; -} - -/*-------------------------------------------------------------------------*/ - -/* prepare all TDs of a transfer */ -static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) -{ - ohci_t *ohci = &gohci; - int data_len = transfer_len; - void *data; - int cnt = 0; - __u32 info = 0; - unsigned int toggle = 0; - - /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ - if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { - toggle = TD_T_TOGGLE; - } else { - toggle = TD_T_DATA0; - usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); - } - urb->td_cnt = 0; - if (data_len) - data = buffer; - else - data = 0; - - switch (usb_pipetype (pipe)) { - case PIPE_BULK: - info = usb_pipeout (pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; - while(data_len > 4096) { - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb); - data += 4096; data_len -= 4096; cnt++; - } - info = usb_pipeout (pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb); - cnt++; - - if (!ohci->sleeping) - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ - break; - - case PIPE_CONTROL: - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill (ohci, info, setup, 8, dev, cnt++, urb); - if (data_len > 0) { - info = usb_pipeout (pipe)? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill (ohci, info, data, data_len, dev, cnt++, urb); - } - info = usb_pipeout (pipe)? - TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (ohci, info, data, 0, dev, cnt++, urb); - if (!ohci->sleeping) - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ - break; - } - if (urb->length != cnt) - dbg("TD LENGTH %d != CNT %d", urb->length, cnt); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - - -/* calculate the transfer length and update the urb */ - -static void dl_transfer_length(td_t * td) -{ - __u32 tdINFO, tdBE, tdCBP; - urb_priv_t *lurb_priv = &urb_priv; - - tdINFO = ohci_cpu_to_le32 (td->hwINFO); - tdBE = ohci_cpu_to_le32 (td->hwBE); - tdCBP = ohci_cpu_to_le32 (td->hwCBP); - - - if (!(usb_pipecontrol(lurb_priv->pipe) && - ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { - if (tdBE != 0) { - if (td->hwCBP == 0) - lurb_priv->actual_length += tdBE - td->data + 1; - else - lurb_priv->actual_length += tdCBP - td->data; - } - } -} - -/*-------------------------------------------------------------------------*/ - -/* replies to the request have to be on a FIFO basis so - * we reverse the reversed done-list */ - -static td_t * dl_reverse_done_list (ohci_t *ohci) -{ - __u32 td_list_hc; - td_t *td_rev = NULL; - td_t *td_list = NULL; - urb_priv_t *lurb_priv = NULL; - - td_list_hc = ohci_cpu_to_le32 (ohci->hcca->done_head) & 0xfffffff0; - ohci->hcca->done_head = 0; - - while (td_list_hc) { - td_list = (td_t *)td_list_hc; - - if (TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO))) { - lurb_priv = &urb_priv; - dbg(" USB-error/status: %x : %p", - TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO)), td_list); - if (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x1)) { - if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) { - td_list->ed->hwHeadP = - (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & ohci_cpu_to_le32 (0xfffffff0)) | - (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x2)); - lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1; - } else - td_list->ed->hwHeadP &= ohci_cpu_to_le32 (0xfffffff2); - } -#ifdef CONFIG_MPC5200 - td_list->hwNextTD = 0; -#endif - } - - td_list->next_dl_td = td_rev; - td_rev = td_list; - td_list_hc = ohci_cpu_to_le32 (td_list->hwNextTD) & 0xfffffff0; - } - return td_list; -} - -/*-------------------------------------------------------------------------*/ - -/* td done list */ -static int dl_done_list (ohci_t *ohci, td_t *td_list) -{ - td_t *td_list_next = NULL; - ed_t *ed; - int cc = 0; - int stat = 0; - /* urb_t *urb; */ - urb_priv_t *lurb_priv; - __u32 tdINFO, edHeadP, edTailP; - - while (td_list) { - td_list_next = td_list->next_dl_td; - - lurb_priv = &urb_priv; - tdINFO = ohci_cpu_to_le32 (td_list->hwINFO); - - ed = td_list->ed; - - dl_transfer_length(td_list); - - /* error code of transfer */ - cc = TD_CC_GET (tdINFO); - if (++(lurb_priv->td_cnt) == lurb_priv->length) { - if ((ed->state & (ED_OPER | ED_UNLINK)) - && (lurb_priv->state != URB_DEL)) { - dbg("ConditionCode %#x", cc); - stat = cc_to_error[cc]; - urb_finished = 1; - } - } - - if (ed->state != ED_NEW) { - edHeadP = ohci_cpu_to_le32 (ed->hwHeadP) & 0xfffffff0; - edTailP = ohci_cpu_to_le32 (ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink (ohci, ed); - } - - td_list = td_list_next; - } - return stat; -} - -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -/* Device descriptor */ -static __u8 root_hub_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x10, /* __u16 bcdUSB; v1.1 */ - 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, - 0x00, /* __u8 iManufacturer; */ - 0x01, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - - -/* Configuration descriptor */ -static __u8 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 */ - 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -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 */ - 'O', /* __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 */ -}; - -/* Hub class-specific descriptor is constructed dynamically */ - - -/*-------------------------------------------------------------------------*/ - -#define OK(x) len = (x); break -#ifdef DEBUG -#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);} -#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);} -#else -#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status) -#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) -#endif -#define RD_RH_STAT roothub_status(&gohci) -#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1) - -/* request to virtual root hub */ - -int rh_check_port_status(ohci_t *controller) -{ - __u32 temp, ndp, i; - int res; - - res = -1; - temp = roothub_a (controller); - ndp = (temp & RH_A_NDP); - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus (controller, i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && - ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - -static int ohci_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 stat = 0; - __u32 datab[4]; - __u8 *data_buf = (__u8 *)datab; - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - -#ifdef DEBUG -urb_priv.actual_length = 0; -pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); -#endif - if (usb_pipeint(pipe)) { - info("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = m16_swap (cmd->value); - wIndex = m16_swap (cmd->index); - wLength = m16_swap (cmd->length); - - info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", - dev->devnum, 8, bmRType_bReq, 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: - *(__u16 *) data_buf = m16_swap (1); OK (2); - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data_buf = m16_swap (0); OK (2); - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data_buf = m16_swap (0); OK (2); - case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data_buf = m32_swap ( - RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); - OK (4); - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): OK (0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - OK(0); - case (RH_C_HUB_OVER_CURRENT): - WR_RH_STAT(RH_HS_OCIC); OK (0); - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): - WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_POCI); OK (0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); - case (RH_C_PORT_CONNECTION): - WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); - case (RH_C_PORT_ENABLE): - WR_RH_PORTSTAT (RH_PS_PESC); OK (0); - case (RH_C_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); - case (RH_C_PORT_OVER_CURRENT): - WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); - case (RH_C_PORT_RESET): - WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); - case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT (RH_PS_PRS); - OK (0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ - if (RD_RH_PORTSTAT & RH_PS_CCS) - WR_RH_PORTSTAT (RH_PS_PES ); - OK (0); - } - break; - - case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_dev_des), - wLength)); - data_buf = root_hub_dev_des; OK(len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; OK(len); - case (0x03): /* string descriptors */ - if(wValue==0x0300) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - OK(len); - } - if(wValue==0x0301) { - len = min_t(unsigned int, - leni, - min_t(unsigned int, - sizeof (root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - OK(len); - } - default: - stat = USB_ST_STALLED; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - { - __u32 temp = roothub_a (&gohci); - - data_buf [0] = 9; /* min length; */ - data_buf [1] = 0x29; - data_buf [2] = temp & RH_A_NDP; - data_buf [3] = 0; - if (temp & RH_A_PSM) /* per-port power switching? */ - data_buf [3] |= 0x1; - if (temp & RH_A_NOCP) /* no overcurrent reporting? */ - data_buf [3] |= 0x10; - else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ - data_buf [3] |= 0x8; - - /* corresponds to data_buf[4-7] */ - datab [1] = 0; - data_buf [5] = (temp & RH_A_POTPGT) >> 24; - temp = roothub_b (&gohci); - data_buf [7] = temp & RH_B_DR; - if (data_buf [2] < 7) { - data_buf [8] = 0xff; - } else { - data_buf [0] += 2; - data_buf [8] = (temp & RH_B_DR) >> 8; - data_buf [10] = data_buf [9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf [0], wLength)); - OK (len); - } - - case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); - - case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); - - default: - dbg ("unsupported root hub command"); - stat = USB_ST_STALLED; - } - -#ifdef DEBUG - ohci_dump_roothub (&gohci, 1); -#endif - - len = min_t(int, len, leni); - if (data != data_buf) - memcpy (data, data_buf, len); - dev->act_len = len; - dev->status = stat; - -#ifdef DEBUG - if (transfer_len) - urb_priv.actual_length = transfer_len; - pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); -#endif - - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/* common code for handling submit messages - used for all but root hub */ -/* accesses. */ -int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup, int interval) -{ - int stat = 0; - int maxsize = usb_maxpacket(dev, pipe); - int timeout; - - /* device pulled? Shortcut the action. */ - if (devgone == dev) { - dev->status = USB_ST_CRC_ERR; - return 0; - } - -#ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); -#endif - if (!maxsize) { - err("submit_common_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - - if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) { - err("sohci_submit_job failed"); - return -1; - } - - /* allow more time for a BULK device to react - some are slow */ -#define BULK_TO 5000 /* timeout in milliseconds */ - if (usb_pipebulk(pipe)) - timeout = BULK_TO; - else - timeout = 100; - - /* wait for it to complete */ - for (;;) { - /* check whether the controller is done */ - stat = hc_interrupt(); - if (stat < 0) { - stat = USB_ST_CRC_ERR; - break; - } - - /* NOTE: since we are not interrupt driven in U-Boot and always - * handle only one URB at a time, we cannot assume the - * transaction finished on the first successful return from - * hc_interrupt().. unless the flag for current URB is set, - * meaning that all TD's to/from device got actually - * transferred and processed. If the current URB is not - * finished we need to re-iterate this loop so as - * hc_interrupt() gets called again as there needs to be some - * more TD's to process still */ - if ((stat >= 0) && (stat != 0xff) && (urb_finished)) { - /* 0xff is returned for an SF-interrupt */ - break; - } - - if (--timeout) { - wait_ms(1); - if (!urb_finished) - dbg("\%"); - - } else { - err("CTL:TIMEOUT "); - dbg("submit_common_msg: TO status %x\n", stat); - stat = USB_ST_CRC_ERR; - urb_finished = 1; - break; - } - } -#if 0 - /* we got an Root Hub Status Change interrupt */ - if (got_rhsc) { -#ifdef DEBUG - ohci_dump_roothub (&gohci, 1); -#endif - got_rhsc = 0; - /* abuse timeout */ - timeout = rh_check_port_status(&gohci); - if (timeout >= 0) { -#if 0 /* this does nothing useful, but leave it here in case that changes */ - /* the called routine adds 1 to the passed value */ - usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); -#endif - /* - * XXX - * This is potentially dangerous because it assumes - * that only one device is ever plugged in! - */ - devgone = dev; - } - } -#endif - - dev->status = stat; - dev->act_len = transfer_len; - -#ifdef DEBUG - pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); -#endif - - /* free TDs in urb_priv */ - urb_free_priv (&urb_priv); - return 0; -} - -/* submit routines called from usb.c */ -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) -{ - info("submit_bulk_msg"); - return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup) -{ - int maxsize = usb_maxpacket(dev, pipe); - - info("submit_control_msg"); -#ifdef DEBUG - urb_priv.actual_length = 0; - pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); -#endif - if (!maxsize) { - err("submit_control_message: pipesize for pipe %lx is zero", - pipe); - return -1; - } - if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { - gohci.rh.dev = dev; - /* root hub - redirect */ - return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, - setup); - } - - return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); -} - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval) -{ - info("submit_int_msg"); - return -1; -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -/* reset the HC and BUS */ - -static int hc_reset (ohci_t *ohci) -{ - int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ - - if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ - writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ - info("USB HC TakeOver from SMM"); - while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { - wait_ms (10); - if (--smm_timeout == 0) { - err("USB HC TakeOver failed!"); - return -1; - } - } - } - - /* Disable HC interrupts */ - writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); - - dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;", - ohci->slot_name, - readl (&ohci->regs->control)); - - /* Reset USB (needed by some controllers) */ - ohci->hc_control = 0; - writel (ohci->hc_control, &ohci->regs->control); - - /* HC Reset requires max 10 us delay */ - writel (OHCI_HCR, &ohci->regs->cmdstatus); - while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { - if (--timeout == 0) { - err("USB HC reset timed out!"); - return -1; - } - udelay (1); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub */ - -static int hc_start (ohci_t * ohci) -{ - __u32 mask; - unsigned int fminterval; - - ohci->disabled = 1; - - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - - writel (0, &ohci->regs->ed_controlhead); - writel (0, &ohci->regs->ed_bulkhead); - - writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ - - fminterval = 0x2edf; - writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel (fminterval, &ohci->regs->fminterval); - writel (0x628, &ohci->regs->lsthresh); - - /* start controller operations */ - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->disabled = 0; - writel (ohci->hc_control, &ohci->regs->control); - - /* disable all interrupts */ - mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | - OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | - OHCI_INTR_OC | OHCI_INTR_MIE); - writel (mask, &ohci->regs->intrdisable); - /* clear all interrupts */ - mask &= ~OHCI_INTR_MIE; - writel (mask, &ohci->regs->intrstatus); - /* Choose the interrupts we care about now - but w/o MIE */ - mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - writel (mask, &ohci->regs->intrenable); - -#ifdef OHCI_USE_NPS - /* required for AMD-756 and some Mac platforms */ - writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, - &ohci->regs->roothub.a); - writel (RH_HS_LPSC, &ohci->regs->roothub.status); -#endif /* OHCI_USE_NPS */ - -#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) - /* POTPGT delay is bits 24-31, in 2 ms units. */ - mdelay ((roothub_a (ohci) >> 23) & 0x1fe); - - /* connect the virtual root hub */ - ohci->rh.devnum = 0; - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static int -hc_interrupt (void) -{ - ohci_t *ohci = &gohci; - struct ohci_regs *regs = ohci->regs; - int ints; - int stat = -1; - - if ((ohci->hcca->done_head != 0) && - !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) { - - ints = OHCI_INTR_WDH; - - } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { - ohci->disabled++; - err ("%s device removed!", ohci->slot_name); - return -1; - - } else if ((ints &= readl (®s->intrenable)) == 0) { - dbg("hc_interrupt: returning..\n"); - return 0xff; - } - - /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ - - if (ints & OHCI_INTR_RHSC) { - got_rhsc = 1; - stat = 0xff; - } - - if (ints & OHCI_INTR_UE) { - ohci->disabled++; - err ("OHCI Unrecoverable Error, controller usb-%s disabled", - ohci->slot_name); - /* e.g. due to PCI Master/Target Abort */ - -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif - /* FIXME: be optimistic, hope that bug won't repeat often. */ - /* Make some non-interrupt context restart the controller. */ - /* Count and limit the retries though; either hardware or */ - /* software errors can go forever... */ - hc_reset (ohci); - return -1; - } - - if (ints & OHCI_INTR_WDH) { - writel (OHCI_INTR_WDH, ®s->intrdisable); - stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); - writel (OHCI_INTR_WDH, ®s->intrenable); - } - - if (ints & OHCI_INTR_SO) { - dbg("USB Schedule overrun\n"); - writel (OHCI_INTR_SO, ®s->intrenable); - stat = -1; - } - - /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ - if (ints & OHCI_INTR_SF) { - unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1; - wait_ms(1); - writel (OHCI_INTR_SF, ®s->intrdisable); - if (ohci->ed_rm_list[frame] != NULL) - writel (OHCI_INTR_SF, ®s->intrenable); - stat = 0xff; - } - - writel (ints, ®s->intrstatus); - return stat; -} - -/*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------------------*/ - -/* De-allocate all resources.. */ - -static void hc_release_ohci (ohci_t *ohci) -{ - dbg ("USB HC release ohci usb-%s", ohci->slot_name); - - if (!ohci->disabled) - hc_reset (ohci); -} - -/*-------------------------------------------------------------------------*/ - -/* - * low level initalisation routine, called from usb.c - */ -static char ohci_inited = 0; - -int usb_lowlevel_init(void) -{ - memset (&gohci, 0, sizeof (ohci_t)); - memset (&urb_priv, 0, sizeof (urb_priv_t)); - - /* align the storage */ - if ((__u32)&ghcca[0] & 0xff) { - err("HCCA not aligned!!"); - return -1; - } - phcca = &ghcca[0]; - info("aligned ghcca %p", phcca); - memset(&ohci_dev, 0, sizeof(struct ohci_device)); - if ((__u32)&ohci_dev.ed[0] & 0x7) { - err("EDs not aligned!!"); - return -1; - } - memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1)); - if ((__u32)gtd & 0x7) { - err("TDs not aligned!!"); - return -1; - } - ptd = gtd; - gohci.hcca = phcca; - memset (phcca, 0, sizeof (struct ohci_hcca)); - - gohci.disabled = 1; - gohci.sleeping = 0; - gohci.irq = -1; -#if defined(CONFIG_440EP) - gohci.regs = (struct ohci_regs *)(CONFIG_SYS_PERIPHERAL_BASE | 0x1000); -#elif defined(CONFIG_440EPX) || defined(CONFIG_SYS_USB_HOST) - gohci.regs = (struct ohci_regs *)(CONFIG_SYS_USB_HOST); -#endif - - gohci.flags = 0; - gohci.slot_name = "ppc440"; - - if (hc_reset (&gohci) < 0) { - hc_release_ohci (&gohci); - return -1; - } - - if (hc_start (&gohci) < 0) { - err ("can't start usb-%s", gohci.slot_name); - hc_release_ohci (&gohci); - return -1; - } - -#ifdef DEBUG - ohci_dump (&gohci, 1); -#endif - ohci_inited = 1; - urb_finished = 1; - -#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) - /* init the device driver */ - usb_dev_init(); -#endif - - return 0; -} - -int usb_lowlevel_stop(void) -{ - /* this gets called really early - before the controller has */ - /* even been initialized! */ - if (!ohci_inited) - return 0; - /* TODO release any interrupts, etc. */ - /* call hc_release_ohci() here ? */ - hc_reset (&gohci); - return 0; -} - -#endif /* CONFIG_USB_OHCI */ diff --git a/arch/powerpc/cpu/ppc4xx/usb_ohci.h b/arch/powerpc/cpu/ppc4xx/usb_ohci.h deleted file mode 100644 index 2c3dc4f..0000000 --- a/arch/powerpc/cpu/ppc4xx/usb_ohci.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> - * - * usb-ohci.h - */ - -static int cc_to_error[16] = { - -/* mapping of the OHCI CC status to error codes */ - /* No Error */ 0, - /* CRC Error */ USB_ST_CRC_ERR, - /* Bit Stuff */ USB_ST_BIT_ERR, - /* Data Togg */ USB_ST_CRC_ERR, - /* Stall */ USB_ST_STALLED, - /* DevNotResp */ -1, - /* PIDCheck */ USB_ST_BIT_ERR, - /* UnExpPID */ USB_ST_BIT_ERR, - /* DataOver */ USB_ST_BUF_ERR, - /* DataUnder */ USB_ST_BUF_ERR, - /* reservd */ -1, - /* reservd */ -1, - /* BufferOver */ USB_ST_BUF_ERR, - /* BuffUnder */ USB_ST_BUF_ERR, - /* Not Access */ -1, - /* Not Access */ -1 -}; - -/* ED States */ - -#define ED_NEW 0x00 -#define ED_UNLINK 0x01 -#define ED_OPER 0x02 -#define ED_DEL 0x04 -#define ED_URB_DEL 0x08 - -/* usb_ohci_ed */ -struct ed { - __u32 hwINFO; - __u32 hwTailP; - __u32 hwHeadP; - __u32 hwNextED; - - struct ed *ed_prev; - __u8 int_period; - __u8 int_branch; - __u8 int_load; - __u8 int_interval; - __u8 state; - __u8 type; - __u16 last_iso; - struct ed *ed_rm_list; - - struct usb_device *usb_dev; - __u32 unused[3]; -} __attribute__((aligned(16))); -typedef struct ed ed_t; - -/* TD info field */ -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_R 0x00040000 -#define TD_DI 0x00E00000 -#define TD_DI_SET(X) (((X) & 0x07)<< 21) -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_ISO 0x00010000 -#define TD_DEL 0x00020000 - -/* CC Codes */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D -#define TD_NOTACCESSED 0x0F - -#define MAXPSW 1 - -struct td { - __u32 hwINFO; - __u32 hwCBP; /* Current Buffer Pointer */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ - - __u16 hwPSW[MAXPSW]; - __u8 unused; - __u8 index; - struct ed *ed; - struct td *next_dl_td; - struct usb_device *usb_dev; - int transfer_len; - __u32 data; - - __u32 unused2[2]; -} __attribute__((aligned(32))); -typedef struct td td_t; - -#define OHCI_ED_SKIP (1 << 14) - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined in the OHCI spec. that the host controller is - * told the base address of. It must be 256-byte aligned. - */ - -#define NUM_INTS 32 /* part of the OHCI standard */ -struct ohci_hcca { - __u32 int_table[NUM_INTS]; /* Interrupt ED table */ -#if defined(CONFIG_MPC5200) - __u16 pad1; /* set to 0 on each frame_no change */ - __u16 frame_no; /* current frame number */ -#else - __u16 frame_no; /* current frame number */ - __u16 pad1; /* set to 0 on each frame_no change */ -#endif - __u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc[116]; -} __attribute__((aligned(256))); - -/* - * Maximum number of root hub ports. - */ -#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ - -/* - * This is the structure of the OHCI controller's memory mapped I/O - * region. This is Memory Mapped I/O. You must use the readl() and - * writel() macros defined in asm/io.h to access these!! - */ -struct ohci_regs { - /* control and status registers */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; - /* memory pointers */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; - /* frame counters */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; - /* Root hub ports */ - struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; - __u32 portstatus[MAX_ROOT_PORTS]; - } roothub; -} __attribute__((aligned(32))); - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - -/* Virtual Root HUB */ -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void *dev; /* was urb */ - void *int_addr; - int send; - int interval; -}; - -/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ - -/* 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 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status */ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -/* urb */ -#define N_URB_TD 48 -typedef struct { - ed_t *ed; - __u16 length; /* number of tds associated with this request */ - __u16 td_cnt; /* number of tds already serviced */ - int state; - unsigned long pipe; - int actual_length; - td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ -} urb_priv_t; -#define URB_DEL 1 - -/* - * This is the full ohci controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - -typedef struct ohci { - struct ohci_hcca *hcca; /* hcca */ - /*dma_addr_t hcca_dma; */ - - int irq; - int disabled; /* e.g. got a UE, we're hung */ - int sleeping; - unsigned long flags; /* for HC bugs */ - - struct ohci_regs *regs; /* OHCI controller's memory */ - - ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ - ed_t *ed_bulktail; /* last endpoint of bulk list */ - ed_t *ed_controltail; /* last endpoint of control list */ - int intrstatus; - __u32 hc_control; /* copy of the hc control reg */ - struct usb_device *dev[32]; - struct virt_root_hub rh; - - const char *slot_name; -} ohci_t; - -#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ - -struct ohci_device { - ed_t ed[NUM_EDS]; - int ed_cnt; -}; - -/* hcd */ -/* endpoint */ -static int ep_link(ohci_t * ohci, ed_t * ed); -static int ep_unlink(ohci_t * ohci, ed_t * ed); -static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe); - -/*-------------------------------------------------------------------------*/ - -/* we need more TDs than EDs */ -#define NUM_TD 64 - -/* +1 so we can align the storage */ -td_t gtd[NUM_TD + 1]; -/* pointers to aligned storage */ -td_t *ptd; - -/* TDs ... */ -static inline struct td *td_alloc(struct usb_device *usb_dev) -{ - int i; - struct td *td; - - td = NULL; - for (i = 0; i < NUM_TD; i++) { - if (ptd[i].usb_dev == NULL) { - td = &ptd[i]; - td->usb_dev = usb_dev; - break; - } - } - - return td; -} - -static inline void ed_free(struct ed *ed) -{ - ed->usb_dev = NULL; -} diff --git a/arch/powerpc/cpu/ppc4xx/usbdev.c b/arch/powerpc/cpu/ppc4xx/usbdev.c deleted file mode 100644 index fe398af..0000000 --- a/arch/powerpc/cpu/ppc4xx/usbdev.c +++ /dev/null @@ -1,230 +0,0 @@ -/*USB 1.1,2.0 device*/ - -#include <common.h> -#include <asm/processor.h> - -#if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && defined(CONFIG_CMD_USB) - -#include <usb.h> -#include <asm/ppc4xx-uic.h> -#include "usbdev.h" - -#define USB_DT_DEVICE 0x01 -#define USB_DT_CONFIG 0x02 -#define USB_DT_STRING 0x03 -#define USB_DT_INTERFACE 0x04 -#define USB_DT_ENDPOINT 0x05 - -int set_value = -1; - -void process_endpoints(unsigned short usb2d0_intrin) -{ - /*will hold the packet received */ - struct usb_device_descriptor usb_device_packet; - struct usb_configuration_descriptor usb_config_packet; - struct usb_string_descriptor usb_string_packet; - struct devrequest setup_packet; - unsigned int *setup_packet_pt; - unsigned char *packet_pt = NULL; - int temp, temp1; - - int i; - - /*printf("{USB device} - endpoint 0x%X \n", usb2d0_intrin); */ - - /*set usb address, seems to not work unless it is done in the next - interrupt, so that is why it is done this way */ - if (set_value != -1) - *(unsigned char *)USB2D0_FADDR_8 = (unsigned char)set_value; - - /*endpoint 1 */ - if (usb2d0_intrin & 0x01) { - setup_packet_pt = (unsigned int *)&setup_packet; - - /*copy packet */ - setup_packet_pt[0] = *(unsigned int *)USB2D0_FIFO_0; - setup_packet_pt[1] = *(unsigned int *)USB2D0_FIFO_0; - temp = *(unsigned int *)USB2D0_FIFO_0; - temp1 = *(unsigned int *)USB2D0_FIFO_0; - - /*do some swapping */ - setup_packet.value = swap_16(setup_packet.value); - setup_packet.index = swap_16(setup_packet.index); - setup_packet.length = swap_16(setup_packet.length); - - /*clear rx packet */ - *(unsigned short *)USB2D0_INCSR0_8 = 0x48; - - /*printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", setup_packet.requesttype, - setup_packet.request, setup_packet.value, - setup_packet.index, setup_packet.length, temp, temp1 ); */ - - switch (setup_packet.request) { - case USB_REQ_GET_DESCRIPTOR: - - switch (setup_packet.value >> 8) { - case USB_DT_DEVICE: - /*create packet */ - usb_device_packet.bLength = 18; - usb_device_packet.bDescriptorType = - USB_DT_DEVICE; -#ifdef USB_2_0_DEVICE - usb_device_packet.bcdUSB = swap_16(0x200); -#else - usb_device_packet.bcdUSB = swap_16(0x110); -#endif - usb_device_packet.bDeviceClass = 0xff; - usb_device_packet.bDeviceSubClass = 0; - usb_device_packet.bDeviceProtocol = 0; - usb_device_packet.bMaxPacketSize0 = 32; - usb_device_packet.idVendor = swap_16(1); - usb_device_packet.idProduct = swap_16(2); - usb_device_packet.bcdDevice = swap_16(0x300); - usb_device_packet.iManufacturer = 1; - usb_device_packet.iProduct = 1; - usb_device_packet.iSerialNumber = 1; - usb_device_packet.bNumConfigurations = 1; - - /*put packet in fifo */ - packet_pt = (unsigned char *)&usb_device_packet; - break; - - case USB_DT_CONFIG: - /*create packet */ - usb_config_packet.bLength = 9; - usb_config_packet.bDescriptorType = - USB_DT_CONFIG; - usb_config_packet.wTotalLength = swap_16(25); - usb_config_packet.bNumInterfaces = 1; - usb_config_packet.bConfigurationValue = 1; - usb_config_packet.iConfiguration = 0; - usb_config_packet.bmAttributes = 0x40; - usb_config_packet.bMaxPower = 0; - - /*put packet in fifo */ - packet_pt = (unsigned char *)&usb_config_packet; - break; - - case USB_DT_STRING: - /*create packet */ - usb_string_packet.bLength = 2; - usb_string_packet.bDescriptorType = - USB_DT_STRING; - usb_string_packet.wData[0] = 0x0094; - - /*put packet in fifo */ - packet_pt = (unsigned char *)&usb_string_packet; - break; - } - - /*put packet in fifo */ - for (i = 0; i < (setup_packet.length); i++) { - *(unsigned char *)USB2D0_FIFO_0 = packet_pt[i]; - } - - /*give tx command */ - *(unsigned short *)USB2D0_INCSR0_8 = 0x0a; - - break; - - case USB_REQ_SET_ADDRESS: - - /*copy usb address */ - set_value = setup_packet.value; - - break; - } - - } -} - -void process_other(unsigned char usb2d0_intrusb) -{ - - /*check for sof */ - if (usb2d0_intrusb & 0x08) { - /*printf("{USB device} - sof detected\n"); */ - } - - /*check for reset */ - if (usb2d0_intrusb & 0x04) { - /*printf("{USB device} - reset detected\n"); */ - - /*copy usb address of zero, need to do this when usb reset */ - set_value = 0; - } - - if (usb2d0_intrusb & 0x02) { - /*printf("{USB device} - resume detected\n"); */ - } - - if (usb2d0_intrusb & 0x01) { - /*printf("{USB device} - suspend detected\n"); */ - } -} - -int usbInt(void) -{ - /*Must read these 2 registers and use values to clear interrupts. If you - do not read them then the interrupt will not be cleared. If you do not - use the variable the optimizer will not do a read. */ - volatile unsigned short usb2d0_intrin = - *(unsigned short *)USB2D0_INTRIN_16; - volatile unsigned char usb2d0_intrusb = - *(unsigned char *)USB2D0_INTRUSB_8; - - /*check if there was an endpoint interrupt */ - if (usb2d0_intrin != 0) { - process_endpoints(usb2d0_intrin); - } - - /*check for other interrupts */ - if (usb2d0_intrusb != 0) { - process_other(usb2d0_intrusb); - } - - return 0; -} - -#if defined(CONFIG_440EPX) -void usb_dev_init() -{ - printf("USB 2.0 Device init\n"); - - /*usb dev init */ - *(unsigned char *)USB2D0_POWER_8 = 0xa1; /* 2.0 */ - - /*enable interrupts */ - *(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f; - - irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt, - NULL); -} -#else -void usb_dev_init() -{ -#ifdef USB_2_0_DEVICE - printf("USB 2.0 Device init\n"); - /*select 2.0 device */ - mtsdr(SDR0_USB0, 0x0); /* 2.0 */ - - /*usb dev init */ - *(unsigned char *)USB2D0_POWER_8 = 0xa1; /* 2.0 */ -#else - printf("USB 1.1 Device init\n"); - /*select 1.1 device */ - mtsdr(SDR0_USB0, 0x2); /* 1.1 */ - - /*usb dev init */ - *(unsigned char *)USB2D0_POWER_8 = 0xc0; /* 1.1 */ -#endif - - /*enable interrupts */ - *(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f; - - irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt, - NULL); -} -#endif - -#endif /* CONFIG_440EP || CONFIG_440EPX */ diff --git a/arch/powerpc/cpu/ppc4xx/usbdev.h b/arch/powerpc/cpu/ppc4xx/usbdev.h deleted file mode 100644 index ef6a2da..0000000 --- a/arch/powerpc/cpu/ppc4xx/usbdev.h +++ /dev/null @@ -1,31 +0,0 @@ -#include <config.h> - -/*Common Registers*/ -#define USB2D0_INTRIN_16 (CONFIG_SYS_USB_DEVICE | 0x100) -#define USB2D0_POWER_8 (CONFIG_SYS_USB_DEVICE | 0x102) -#define USB2D0_FADDR_8 (CONFIG_SYS_USB_DEVICE | 0x103) -#define USB2D0_INTRINE_16 (CONFIG_SYS_USB_DEVICE | 0x104) -#define USB2D0_INTROUT_16 (CONFIG_SYS_USB_DEVICE | 0x106) -#define USB2D0_INTRUSBE_8 (CONFIG_SYS_USB_DEVICE | 0x108) -#define USB2D0_INTRUSB_8 (CONFIG_SYS_USB_DEVICE | 0x109) -#define USB2D0_INTROUTE_16 (CONFIG_SYS_USB_DEVICE | 0x10a) -#define USB2D0_TSTMODE_8 (CONFIG_SYS_USB_DEVICE | 0x10c) -#define USB2D0_INDEX_8 (CONFIG_SYS_USB_DEVICE | 0x10d) -#define USB2D0_FRAME_16 (CONFIG_SYS_USB_DEVICE | 0x10e) - -/*Indexed Registers*/ -#define USB2D0_INCSR0_8 (CONFIG_SYS_USB_DEVICE | 0x110) -#define USB2D0_INCSR_16 (CONFIG_SYS_USB_DEVICE | 0x110) -#define USB2D0_INMAXP_16 (CONFIG_SYS_USB_DEVICE | 0x112) -#define USB2D0_OUTCSR_16 (CONFIG_SYS_USB_DEVICE | 0x114) -#define USB2D0_OUTMAXP_16 (CONFIG_SYS_USB_DEVICE | 0x116) -#define USB2D0_OUTCOUNT0_8 (CONFIG_SYS_USB_DEVICE | 0x11a) -#define USB2D0_OUTCOUNT_16 (CONFIG_SYS_USB_DEVICE | 0x11a) - -/*FIFOs*/ -#define USB2D0_FIFO_0 (CONFIG_SYS_USB_DEVICE | 0x120) -#define USB2D0_FIFO_1 (CONFIG_SYS_USB_DEVICE | 0x124) -#define USB2D0_FIFO_2 (CONFIG_SYS_USB_DEVICE | 0x128) -#define USB2D0_FIFO_3 (CONFIG_SYS_USB_DEVICE | 0x12c) - -void usb_dev_init(void); diff --git a/arch/powerpc/cpu/ppc4xx/xilinx_irq.c b/arch/powerpc/cpu/ppc4xx/xilinx_irq.c deleted file mode 100644 index eaa3de2..0000000 --- a/arch/powerpc/cpu/ppc4xx/xilinx_irq.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * (C) Copyright 2008 - * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es - * This work has been supported by: QTechnology http://qtec.com/ - * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de - * 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, see <http://www.gnu.org/licenses/>. -*/ -#include <common.h> -#include <watchdog.h> -#include <command.h> -#include <asm/processor.h> -#include <asm/interrupt.h> -#include <asm/ppc4xx.h> -#include <ppc_asm.tmpl> -#include <commproc.h> -#include <asm/io.h> -#include <asm/xilinx_irq.h> - -DECLARE_GLOBAL_DATA_PTR; - -void pic_enable(void) -{ - debug("Xilinx PIC at 0x%8x\n", intc); - - /* - * Disable all external interrupts until they are - * explicitly requested. - */ - out_be32((u32 *) IER, 0); - - /* Acknowledge any pending interrupts just in case. */ - out_be32((u32 *) IAR, 0xffffffff); - - /* Turn on the Master Enable. */ - out_be32((u32 *) MER, 0x3UL); - - return; -} - -int xilinx_pic_irq_get(void) -{ - u32 irq; - irq = in_be32((u32 *) IVR); - - /* If no interrupt is pending then all bits of the IVR are set to 1. As - * the IVR is as many bits wide as numbers of inputs are available. - * Therefore, if all bits of the IVR are set to one, its content will - * be bigger than XPAR_INTC_MAX_NUM_INTR_INPUTS. - */ - if (irq >= XPAR_INTC_MAX_NUM_INTR_INPUTS) - irq = -1; /* report no pending interrupt. */ - - debug("get_irq: %d\n", irq); - return (irq); -} - -void pic_irq_enable(unsigned int irq) -{ - u32 mask = IRQ_MASK(irq); - debug("enable: %d\n", irq); - out_be32((u32 *) SIE, mask); -} - -void pic_irq_disable(unsigned int irq) -{ - u32 mask = IRQ_MASK(irq); - debug("disable: %d\n", irq); - out_be32((u32 *) CIE, mask); -} - -void pic_irq_ack(unsigned int irq) -{ - u32 mask = IRQ_MASK(irq); - debug("ack: %d\n", irq); - out_be32((u32 *) IAR, mask); -} - -void external_interrupt(struct pt_regs *regs) -{ - int irq; - - irq = xilinx_pic_irq_get(); - if (irq < 0) - return; - - interrupt_run_handler(irq); - - return; -} |