mpc86xx: set the DDR BATs after calculating true DDR size

After determining how much DDR is actually in the system, set DBAT0 and
IBAT0 accordingly.  This ensures that the CPU won't attempt to access
(via speculation) addresses outside of actual memory.

On 86xx systems, DBAT0 and IBAT0 (the BATs for DDR) are initialized to 2GB
and kept that way.  If the system has less than 2GB of memory (typical for
an MPC8610 HPCD), the CPU may attempt to access this memory during
speculation.  The zlib code is notorious for generating such memory reads,
and indeed on the MPC8610, uncompressing the Linux kernel causes a machine
check (without this patch).

Currently we are limited to power of two sized DDR since we only use a
single bat.  If a non-power of two size is used that is less than
CONFIG_MAX_MEM_MAPPED u-boot will crash.

Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
Timur Tabi 2010-03-29 12:51:07 -05:00 committed by Kumar Gala
parent 33f57bd553
commit 9ff32d8ccf
8 changed files with 53 additions and 9 deletions

View File

@ -127,6 +127,8 @@ initdram(int board_type)
dram_size = fixed_sdram();
#endif
setup_ddr_bat(dram_size);
puts(" DDR: ");
return dram_size;
}

View File

@ -74,6 +74,8 @@ initdram(int board_type)
dram_size = fixed_sdram();
#endif
setup_ddr_bat(dram_size);
puts(" DDR: ");
return dram_size;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006,2009 Freescale Semiconductor, Inc.
* Copyright 2006,2009-2010 Freescale Semiconductor, Inc.
* Jeff Brown
* Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
*
@ -197,3 +197,37 @@ void mpc86xx_reginfo(void)
printf("\tBR7\t0x%08X\tOR7\t0x%08X \n", in_be32(&lbc->br7), in_be32(&lbc->or7));
}
/*
* Set the DDR BATs to reflect the actual size of DDR.
*
* dram_size is the actual size of DDR, in bytes
*
* Note: we assume that CONFIG_MAX_MEM_MAPPED is 2G or smaller as we only
* are using a single BAT to cover DDR.
*
* If this is not true, (e.g. CONFIG_MAX_MEM_MAPPED is 2GB but HID0_XBSEN
* is not defined) then we might have a situation where U-Boot will attempt
* to relocated itself outside of the region mapped by DBAT0.
* This will cause a machine check.
*
* Currently we are limited to power of two sized DDR since we only use a
* single bat. If a non-power of two size is used that is less than
* CONFIG_MAX_MEM_MAPPED u-boot will crash.
*
*/
void setup_ddr_bat(phys_addr_t dram_size)
{
unsigned long batu, bl;
bl = TO_BATU_BL(min(dram_size, CONFIG_MAX_MEM_MAPPED));
if (BATU_SIZE(bl) != dram_size) {
u64 sz = (u64)dram_size - BATU_SIZE(bl);
print_size(sz, " left unmapped\n");
}
batu = bl | BATU_VS | BATU_VP;
write_bat(DBAT0, batu, CONFIG_SYS_DBAT0L);
write_bat(IBAT0, batu, CONFIG_SYS_IBAT0L);
}

View File

@ -138,8 +138,12 @@ int cpu_init_r(void)
/* Set up BAT registers */
void setup_bats(void)
{
#if defined(CONFIG_SYS_DBAT0U) && defined(CONFIG_SYS_DBAT0L)
write_bat(DBAT0, CONFIG_SYS_DBAT0U, CONFIG_SYS_DBAT0L);
#endif
#if defined(CONFIG_SYS_IBAT0U) && defined(CONFIG_SYS_IBAT0L)
write_bat(IBAT0, CONFIG_SYS_IBAT0U, CONFIG_SYS_IBAT0L);
#endif
write_bat(DBAT1, CONFIG_SYS_DBAT1U, CONFIG_SYS_DBAT1L);
write_bat(IBAT1, CONFIG_SYS_IBAT1U, CONFIG_SYS_IBAT1L);
write_bat(DBAT2, CONFIG_SYS_DBAT2U, CONFIG_SYS_DBAT2L);

View File

@ -213,7 +213,11 @@ extern void print_bats(void);
#define BATL_PADDR(x) ((phys_addr_t)((x & 0xfffe0000) \
| ((x & 0x0e00ULL) << 24) \
| ((x & 0x04ULL) << 30)))
#define BATU_SIZE(x) (1UL << (fls((x & BATU_BL_MAX) >> 2) + 17))
#define BATU_SIZE(x) (1ULL << (fls((x & BATU_BL_MAX) >> 2) + 17))
/* bytes into BATU_BL */
#define TO_BATU_BL(x) \
(u32)((((1ull << __ilog2_u64((u64)x)) / (128 * 1024)) - 1) * 4)
/* Used to set up SDR1 register */
#define HASH_TABLE_SIZE_64K 0x00010000

View File

@ -341,10 +341,8 @@
* BAT0 2G Cacheable, non-guarded
* 0x0000_0000 2G DDR
*/
#define CONFIG_SYS_DBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE)
#define CONFIG_SYS_DBAT0U (BATU_BL_2G | BATU_VS | BATU_VP)
#define CONFIG_SYS_IBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE )
#define CONFIG_SYS_IBAT0U CONFIG_SYS_DBAT0U
#define CONFIG_SYS_DBAT0L (BATL_PP_RW)
#define CONFIG_SYS_IBAT0L (BATL_PP_RW)
/*
* BAT1 1G Cache-inhibited, guarded

View File

@ -482,9 +482,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
* BAT0 DDR
*/
#define CONFIG_SYS_DBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE)
#define CONFIG_SYS_DBAT0U (BATU_BL_2G | BATU_VS | BATU_VP)
#define CONFIG_SYS_IBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE )
#define CONFIG_SYS_IBAT0U CONFIG_SYS_DBAT0U
#define CONFIG_SYS_IBAT0L (BATL_PP_RW | BATL_MEMCOHERENCE)
/*
* BAT1 LBC (PIXIS/CF)

View File

@ -83,5 +83,7 @@ static __inline__ unsigned long get_l2cr (void)
return l2cr_val;
}
void setup_ddr_bat(phys_addr_t dram_size);
#endif /* _ASMLANGUAGE */
#endif /* __MPC86xx_H__ */