[U-Boot] [v3] command/cache: Add flush command

Wolfgang Denk wd at denx.de
Tue Apr 9 19:45:31 CEST 2013


Dear Scott,

In message <1365449512.28843.10 at snotra> you wrote:
>
> > > Maybe "cache" should be the toplevel command, with "icache" and
> > > "dcache" refactored to be subcommands?  Of course, then you're making
> > > an incompatible interface change.  How much is consistency worth?
> > 
> > I think backward compatibility is mandatory here.  We cannot break
> > existing user scripts.
>
> Sure.  But if the main reason for the icache/dcache split is  
> compatibility, I don't think that should constrict the form of new  
> commands.

Backward compatibility is just the argument for not changing the
existing command interfaces.  I tried to explain why I do not want
to see the flush_cache() combination of functions exposed to end
users.

> I think the terminology is just fine.  It's not just invalidating the  
> icache (flushing and invalidating are the same thing for cache lines  
> which are not modified -- or are incapable of being modified).  It's  
> flushing the region out of *all* caches.

There is a well-defined difference between flushing and invalidating a
cache, and I don't intend to go into hair-splitting mode here just to
follow your path which would lead me to where I d not want to go.

> > See above.  In such a case "icache" and "dcache" can just call the
> > same underlying code.
>
> And then we end up having to do the flush twice, if the user follows  
> the "first flush dcache, then flush icache" instructions.  That's not  
> an ideal interface.

OK, this is indeed a good argument.  But is this really the case?
When looking at the current code of flash_cache() for PPC, it seems
actually easy to split:

 28 void flush_cache(ulong start_addr, ulong size)
 29 {
 30 #ifndef CONFIG_5xx
 31         ulong addr, start, end;
 32
 33         start = start_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
 34         end = start_addr + size - 1;
 35
 36         for (addr = start; (addr <= end) && (addr >= start);
 37                         addr += CONFIG_SYS_CACHELINE_SIZE) {
 38                 asm volatile("dcbst 0,%0" : : "r" (addr) : "memory");
 39                 WATCHDOG_RESET();
 40         }
 41         /* wait for all dcbst to complete on bus */
 42         asm volatile("sync" : : : "memory");
 43
 44         for (addr = start; (addr <= end) && (addr >= start);
 45                         addr += CONFIG_SYS_CACHELINE_SIZE) {
 46                 asm volatile("icbi 0,%0" : : "r" (addr) : "memory");
 47                 WATCHDOG_RESET();
 48         }
 49         asm volatile("sync" : : : "memory");
 50         /* flush prefetch queue */
 51         asm volatile("isync" : : : "memory");
 52 #endif
 53 }

Lines 36..42 would go into the "dcache" command, while lines 44..51
would go into the "icache" command.

So far this code appears to work fine.  What am I missing?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
You don't stop doing things because you get old.  You get old because
you stop doing things.                            - Rosamunde Pilcher


More information about the U-Boot mailing list