Fix a bug and stick nearer to the specification, introduce armv6_unified.

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-05-17 13:05:28 +02:00
parent 390df92f0b
commit 470038745c

View file

@ -2,10 +2,13 @@
#include <grub/cache.h> #include <grub/cache.h>
#include <grub/arm/system.h> #include <grub/arm/system.h>
/* This is only about cache architecture. It doesn't imply
the CPU architecture. */
static enum static enum
{ {
ARCH_UNKNOWN, ARCH_UNKNOWN,
ARCH_ARMV6, ARCH_ARMV6,
ARCH_ARMV6_UNIFIED,
ARCH_ARMV7 ARCH_ARMV7
} type = ARCH_UNKNOWN; } type = ARCH_UNKNOWN;
@ -23,7 +26,7 @@ probe_caches (void)
{ {
grub_uint32_t main_id, cache_type; grub_uint32_t main_id, cache_type;
/* Read Cache Type Register */ /* Read main ID Register */
asm volatile ("mrc p15, 0, %0, c0, c0, 0": "=r"(main_id)); asm volatile ("mrc p15, 0, %0, c0, c0, 0": "=r"(main_id));
if (((main_id >> 12) & 0xf) == 0x0 || ((main_id >> 12) & 0xf) == 0x7 if (((main_id >> 12) & 0xf) == 0x0 || ((main_id >> 12) & 0xf) == 0x7
@ -33,17 +36,31 @@ probe_caches (void)
/* Read Cache Type Register */ /* Read Cache Type Register */
asm volatile ("mrc p15, 0, %0, c0, c0, 1": "=r"(cache_type)); asm volatile ("mrc p15, 0, %0, c0, c0, 1": "=r"(cache_type));
switch (cache_type >> 29) switch (cache_type >> 24)
{ {
case 0: case 0x04:
case 0x0a:
case 0x0c:
case 0x0e:
case 0x1c:
grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3);
grub_arch_cache_ilinesz = 8 << (cache_type & 3);
type = ARCH_ARMV6_UNIFIED;
break;
case 0x05:
case 0x0b:
case 0x0d:
case 0x0f:
case 0x1d:
grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3); grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3);
grub_arch_cache_ilinesz = 8 << (cache_type & 3); grub_arch_cache_ilinesz = 8 << (cache_type & 3);
type = ARCH_ARMV6; type = ARCH_ARMV6;
break; break;
case 4: case 0x80 ... 0x9f:
grub_arch_cache_dlinesz = 4 << ((cache_type >> 16) & 0xf); grub_arch_cache_dlinesz = 4 << ((cache_type >> 16) & 0xf);
grub_arch_cache_ilinesz = 4 << (cache_type & 0xf); grub_arch_cache_ilinesz = 4 << (cache_type & 0xf);
type = ARCH_ARMV7; type = ARCH_ARMV7;
break;
default: default:
grub_fatal ("Unsupported cache type 0x%x", cache_type); grub_fatal ("Unsupported cache type 0x%x", cache_type);
} }
@ -54,10 +71,21 @@ grub_arch_sync_caches (void *address, grub_size_t len)
{ {
if (type == ARCH_UNKNOWN) if (type == ARCH_UNKNOWN)
probe_caches (); probe_caches ();
if (type == ARCH_ARMV6) switch (type)
grub_arch_sync_caches_armv6 (address, len); {
if (type == ARCH_ARMV7) case ARCH_ARMV6:
grub_arch_sync_caches_armv7 (address, len); grub_arch_sync_caches_armv6 (address, len);
break;
case ARCH_ARMV7:
grub_arch_sync_caches_armv7 (address, len);
break;
/* Nothing to do. */
case ARCH_ARMV6_UNIFIED:
break;
/* Pacify GCC. */
case ARCH_UNKNOWN:
break;
}
} }
void void
@ -65,8 +93,17 @@ grub_arm_disable_caches_mmu (void)
{ {
if (type == ARCH_UNKNOWN) if (type == ARCH_UNKNOWN)
probe_caches (); probe_caches ();
if (type == ARCH_ARMV6) switch (type)
grub_arm_disable_caches_mmu_armv6 (); {
if (type == ARCH_ARMV7) case ARCH_ARMV6_UNIFIED:
grub_arm_disable_caches_mmu_armv7 (); case ARCH_ARMV6:
grub_arm_disable_caches_mmu_armv6 ();
break;
case ARCH_ARMV7:
grub_arm_disable_caches_mmu_armv7 ();
break;
/* Pacify GCC. */
case ARCH_UNKNOWN:
break;
}
} }