X-Git-Url: http://git.ipfire.org/?p=people%2Fms%2Fu-boot.git;a=blobdiff_plain;f=arch%2Farc%2Flib%2Fcache.c;h=d8741fe959c3fc7ddec39ecaf6bfaa7443cb8d38;hp=b6ec83112cd8aa5264d9572c9ef97fbf0f9462ce;hb=f2a226780fa0e4055bec636b8108bf7e80951174;hpb=2313d48445e59f063ec9a3b4940fe8252737db76 diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index b6ec83112c..d8741fe959 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -59,10 +60,16 @@ static unsigned int __before_slc_op(const int op) static void __after_slc_op(const int op, unsigned int reg) { - if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ + if (op & OP_FLUSH) { /* flush / flush-n-inv both wait */ + /* + * Make sure "busy" bit reports correct status, + * see STAR 9001165532 + */ + read_aux_reg(ARC_AUX_SLC_CTRL); while (read_aux_reg(ARC_AUX_SLC_CTRL) & DC_CTRL_FLUSH_STATUS) ; + } /* Switch back to default Invalidate mode */ if (op == OP_INV) @@ -209,17 +216,33 @@ void cache_init(void) read_decode_cache_bcr_arcv2(); if (ioc_exists) { + /* IOC Aperture start is equal to DDR start */ + unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; + /* IOC Aperture size is equal to DDR size */ + long ap_size = CONFIG_SYS_SDRAM_SIZE; + flush_dcache_all(); invalidate_dcache_all(); - /* IO coherency base - 0x8z */ - write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, 0x80000); - /* IO coherency aperture size - 512Mb: 0x8z-0xAz */ - write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, 0x11); - /* Enable partial writes */ + if (!is_power_of_2(ap_size) || ap_size < 4096) + panic("IOC Aperture size must be power of 2 and bigger 4Kib"); + + /* + * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, + * so setting 0x11 implies 512M, 0x12 implies 1G... + */ + write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, + order_base_2(ap_size/1024) - 2); + + + /* IOC Aperture start must be aligned to the size of the aperture */ + if (ap_base % ap_size != 0) + panic("IOC Aperture start must be aligned to the size of the aperture"); + + write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); - /* Enable IO coherency */ write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); + } #endif } @@ -255,6 +278,13 @@ void invalidate_icache_all(void) /* Any write to IC_IVIC register triggers invalidation of entire I$ */ if (icache_status()) { write_aux_reg(ARC_AUX_IC_IVIC, 1); + /* + * As per ARC HS databook (see chapter 5.3.3.2) + * it is required to add 3 NOPs after each write to IC_IVIC. + */ + __builtin_arc_nop(); + __builtin_arc_nop(); + __builtin_arc_nop(); read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ } }