1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * This software may be distributed and modified according to the terms of 5 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 6 * See "LICENSE_GPLv2.txt" for details. 7 * 8 * @TAG(GD_GPL) 9 */ 10 11#include <config.h> 12#include <api/types.h> 13#include <arch/machine.h> 14#include <arch/machine/hardware.h> 15#include <util.h> 16 17/* Prototyped here as this is referenced from assembly */ 18void arm_errata(void); 19 20#ifdef ARM1136_WORKAROUND 21/* 22 * Potentially work around ARM1136 errata #364296, which can cause data 23 * cache corruption. 24 * 25 * The fix involves disabling hit-under-miss via an undocumented bit in 26 * the aux control register, as well as the FI bit in the control 27 * register. The result of enabling these two bits is for fast 28 * interrupts to *not* be enabled, but hit-under-miss to be disabled. We 29 * only need to do this for a particular revision of the ARM1136. 30 */ 31BOOT_CODE static void 32errata_arm1136(void) 33{ 34 /* See if we are affected by the errata. */ 35 if ((getProcessorID() & ~0xf) == ARM1136_R0PX) { 36 37 /* Enable the Fast Interrupts bit in the control register. */ 38 writeSystemControlRegister( 39 readSystemControlRegister() | BIT(CONTROL_FI)); 40 41 /* Set undocumented bit 31 in the auxiliary control register */ 42 writeAuxiliaryControlRegister( 43 readAuxiliaryControlRegister() | BIT(31)); 44 } 45} 46#endif 47 48#ifdef CONFIG_ARM_ERRATA_773022 49/* 50 * There is an errata for Cortex-A15 up to r0p4 where the loop buffer 51 * may deliver incorrect instructions. The work around is to disable 52 * the loop buffer. Errata is number 773022. 53 */ 54BOOT_CODE static void errata_armA15_773022(void) 55{ 56 /* Fetch the processor primary part number. */ 57 uint32_t proc_id = getProcessorID(); 58 uint32_t variant = (proc_id >> 20) & MASK(4); 59 uint32_t revision = proc_id & MASK(4); 60 uint32_t part = (proc_id >> 4) & MASK(12); 61 62 /* Check that we are running A15 and a revision upto r0p4. */ 63 if (part == 0xc0f && variant == 0 && revision <= 4) { 64 /* Disable loop buffer in the auxiliary control register */ 65 writeAuxiliaryControlRegister( 66 readAuxiliaryControlRegister() | BIT(1)); 67 } 68} 69#endif 70 71BOOT_CODE void VISIBLE arm_errata(void) 72{ 73#ifdef ARM1136_WORKAROUND 74 errata_arm1136(); 75#endif 76#ifdef CONFIG_ARM_ERRATA_773022 77 errata_armA15_773022(); 78#endif 79} 80 81